ezllm 0.0.39 → 0.0.40

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 (32) hide show
  1. package/README.md +2 -2
  2. package/dist/cli.js +22 -22
  3. package/dist/daemon.js +3 -3
  4. package/dist/plugin-host.js +3 -3
  5. package/dist/server.js +65 -65
  6. package/dist/web-ui/assets/{DashboardView-STI4Bkxw.js → DashboardView-C0baZH6c.js} +1 -1
  7. package/dist/web-ui/assets/{LayoutView-DHXc1jcz.js → LayoutView-BMNKjFyW.js} +1 -1
  8. package/dist/web-ui/assets/{LoginView-CwH6eISd.js → LoginView-C3CW0urr.js} +1 -1
  9. package/dist/web-ui/assets/{LogsView-CGgzVbGZ.js → LogsView-C70vgFde.js} +1 -1
  10. package/dist/web-ui/assets/{ManagedServicesView-BvzeGhcb.js → ManagedServicesView-dC-MR3OW.js} +1 -1
  11. package/dist/web-ui/assets/PluginsView-B7CeBD8Q.js +2 -0
  12. package/dist/web-ui/assets/PluginsView-ggYmqCJ8.css +1 -0
  13. package/dist/web-ui/assets/ProvidersView-B8l3DcZY.js +14 -0
  14. package/dist/web-ui/assets/{ProvidersView-BpBOF4eX.css → ProvidersView-BSFjmX9y.css} +1 -1
  15. package/dist/web-ui/assets/{ServiceStatusView-BvuFCgT-.js → ServiceStatusView-DpGDJHh9.js} +1 -1
  16. package/dist/web-ui/assets/{SettingsView-W9bjQ9ly.js → SettingsView-CqUrHj3w.js} +1 -1
  17. package/dist/web-ui/assets/{SetupView-D5KYolFQ.js → SetupView-B_hE_Uhm.js} +1 -1
  18. package/dist/web-ui/assets/{config-CX31TfJ4.js → config-IC8ZbooF.js} +1 -1
  19. package/dist/web-ui/assets/{index-D6ydfwRk.js → index-D2JhqxaS.js} +1 -1
  20. package/dist/web-ui/assets/{message-B022-tc2.js → message-Cp_GAwQs.js} +1 -1
  21. package/dist/web-ui/assets/{providers-C6QKdfzy.js → providers-BwuaO9o9.js} +1 -1
  22. package/dist/web-ui/assets/{router-Daxct41S.js → router-BzfmTCjF.js} +2 -2
  23. package/dist/web-ui/assets/{useCopyToast-0dz9T4-H.js → useCopyToast-BpTqycuM.js} +1 -1
  24. package/dist/web-ui/assets/{useManagerApi-DdgACgsq.js → useManagerApi-lFkQleJX.js} +1 -1
  25. package/dist/web-ui/assets/{useQuickRangeFilter-D8oTOMUp.js → useQuickRangeFilter-DmQyTw4A.js} +1 -1
  26. package/dist/web-ui/assets/useToast-D3xB24vj.js +1 -0
  27. package/dist/web-ui/index.html +3 -3
  28. package/package.json +1 -1
  29. package/dist/web-ui/assets/PluginsView-CNDVeVj8.js +0 -2
  30. package/dist/web-ui/assets/PluginsView-zyTILSF1.css +0 -1
  31. package/dist/web-ui/assets/ProvidersView-DTIx2VSi.js +0 -14
  32. package/dist/web-ui/assets/useToast-nQZ8k6t7.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 b,sn as ne,vt as x,w as S}from"./router-Daxct41S.js";import{t as C}from"./useManagerApi-DdgACgsq.js";import{t as w}from"./providers-C6QKdfzy.js";import{n as T,t as E}from"./useCopyToast-0dz9T4-H.js";import{n as D,t as re}from"./useQuickRangeFilter-D8oTOMUp.js";import{f as O,n as k,p as A,r as j,t as M,u as N}from"./format-7jzqzMS_.js";x();function ie(e){let{loadError:t,run:n}=T(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(),x(),u();var ae={class:`flex-col-gap`},oe={class:`kv-grid`},se={class:`kv-label`},ce={class:`kv-value`},le=[`onClick`],ue={class:`kv-item kv-span-2`},de={class:`kv-value`},fe={key:1,class:`kv-unit`},pe={class:`kv-item`},me={class:`kv-value`},he={class:`kv-unit`},ge={class:`kv-item`},_e={class:`kv-value`},ve={class:`flex-between card-header-wrap`},ye={class:`flex-gap-8`},be={class:`usage-grid`},xe={class:`usage-cell`},Se={class:`usage-num orange`},Ce={class:`usage-cell`},we={class:`usage-num blue`},Te={class:`usage-cell`},Ee={class:`usage-num green`},De={class:`usage-cell`},Oe={class:`usage-num purple`},ke={class:`usage-cell`},Ae={class:`usage-num purple`},je={key:0,class:`usage-cell`},Me={class:`usage-num gray`},Ne={class:`usage-cell`},Pe={class:`usage-num blue`},Fe={class:`usage-cell`},Ie=[`title`],Le={class:`usage-cell`},Re=[`title`],ze={key:0},Be=[`onClick`],Ve=[`title`],He=[`title`],P=n({__name:`DashboardView`,setup(n){let l=w(),{copyWithToast:u}=E(),{loadError:x,track:T,retry:P}=ie(),Ue={local:`本机 API 地址`,lan:`局域网地址`,other:`API 地址`},F=c(null),I=c(!0),L=c(``),{rangeKey:R,dateRange:z,onRangeChange:We}=re(()=>B(),`today`),Ge=()=>{R.value=``,B()},Ke=i(()=>{let e=new Set;for(let t of l.suppliers)for(let n of t.models)e.add(n.modelName);if(F.value?.models)for(let t of F.value.models)e.add(t.model);return[...e].sort()}),qe=D(),B=T(async()=>{let e=qe();I.value=!0;try{let t=new URLSearchParams;L.value&&t.set(`model`,L.value),z.value?.length===2&&(t.set(`startDate`,z.value[0]),t.set(`endDate`,z.value[1]));let n=t.toString(),r=await f.get(`/api/usage${n?`?${n}`:``}`);if(!e())return;F.value=r}catch(t){if(!e())return;throw t}finally{e()&&(I.value=!1)}}),Je=D(),V=T(async()=>{let e=Je();try{await Promise.all([B(),l.loadProviders()])}catch(t){if(!e())return;throw t}finally{e()&&(I.value=!1)}}),Ye=()=>P(V),H=window.location.hostname,U=Number(window.location.port)||null,W=i(()=>j({protocol:window.location.protocol,hostname:H,port:U})),G=c(null),K=c(null),q=c(!1),J=c(!0),Y=c(Date.now()),X=c(null),Z=c([]),Q=i(()=>X.value??U),Xe=e=>j({protocol:`http:`,hostname:e,port:Q.value}),Ze=i(()=>H===`127.0.0.1`||H===`::1`||H===`localhost`?`local`:Z.value.includes(H)?`lan`:`other`),$=i(()=>Q.value?Z.value.map(Xe).filter(e=>e!==W.value):[]),Qe=i(()=>{let e=Q.value?Xe(`127.0.0.1`):``;return e!==``&&e!==W.value?e:``}),$e=i(()=>{let e=[];return Ze.value===`lan`?e.push({label:`局域网地址`,values:[W.value,...$.value]}):(e.push({label:Ue[Ze.value],values:[W.value]}),$.value.length>0&&e.push({label:`局域网地址`,values:$.value})),Qe.value!==``&&e.push({label:`本机 API 地址`,values:[Qe.value]}),e.map((t,n)=>({...t,span2:e.length%2==1&&n===e.length-1}))}),et=async()=>{let[e,t]=await Promise.allSettled([C.processes(),f.get(`/api/status`)]);if(J.value=!1,e.status===`fulfilled`&&(G.value=e.value[0]??null),t.status===`rejected`){K.value=null,q.value=!0;return}let n=t.value?.masterKey;K.value=typeof n==`string`?n:null,q.value=typeof n!=`string`;let r=t.value?.listenPort;X.value=typeof r==`number`&&r>0?r:null;let i=t.value?.lanAddresses;Z.value=Array.isArray(i)?i.filter(e=>typeof e==`string`):[],Y.value=Date.now()},tt=e=>{if(!e.startedAt)return`-`;let t=Math.max(0,Math.floor((Y.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(` `)},nt=i(()=>q.value?`获取失败,请刷新重试`:K.value===null?`-`:`未设置(/v1 免鉴权)`),rt;return d(()=>{V(),et(),rt=window.setInterval(et,1e4)}),s(()=>window.clearInterval(rt)),(n,i)=>{let s=g(`el-button`),c=g(`el-alert`),l=g(`el-card`),d=g(`el-option`),f=g(`el-select`),C=g(`el-date-picker`),w=g(`el-table-column`),T=g(`el-table`),E=g(`el-empty`),D=ee(`loading`);return m(),r(`div`,ae,[o(x)?(m(),e(c,{key:0,title:o(x),type:`error`,"show-icon":``,closable:!1},{default:y(()=>[t(s,{size:`small`,onClick:Ye},{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`,oe,[(m(!0),r(S,null,b($e.value,e=>(m(),r(`div`,{key:e.label+e.values[0],class:ne([`kv-item`,{"kv-span-2":e.span2}])},[v(`div`,se,h(e.label),1),v(`div`,ce,[(m(!0),r(S,null,b(e.values,e=>(m(),r(`div`,{key:e},[v(`span`,{class:`copy-text`,onClick:t=>o(u)(e)},h(e),9,le)]))),128))])],2))),128)),v(`div`,ue,[i[6]||=v(`div`,{class:`kv-label`},`API 密钥`,-1),v(`div`,de,[K.value?(m(),r(`span`,{key:0,class:`copy-text`,onClick:i[0]||=e=>o(u)(K.value)},h(K.value),1)):_(``,!0),K.value?(m(),r(`span`,fe,`(/v1 需 Bearer 认证)`)):(m(),r(S,{key:2},[a(h(nt.value),1)],64))])]),v(`div`,pe,[i[9]||=v(`div`,{class:`kv-label`},`运行状态`,-1),v(`div`,me,[G.value?(m(),r(S,{key:0},[i[7]||=v(`span`,{class:`status-dot running`},null,-1),i[8]||=a(`运行中 `,-1),v(`span`,he,`PID `+h(G.value.pid??`-`),1)],64)):(m(),r(S,{key:1},[a(`-`)],64))])]),v(`div`,ge,[i[10]||=v(`div`,{class:`kv-label`},`运行时长`,-1),v(`div`,_e,h(G.value?tt(G.value):`-`),1)])])),[[D,I.value||J.value]])]),_:1}),F.value?(m(),e(l,{key:1,shadow:`never`},{header:y(()=>[v(`div`,ve,[i[12]||=v(`span`,{class:`fw-600`},`用量统计`,-1),v(`div`,ye,[t(f,{modelValue:L.value,"onUpdate:modelValue":i[1]||=e=>L.value=e,placeholder:`全部模型`,clearable:``,filterable:``,style:{width:`220px`},onChange:o(B)},{default:y(()=>[(m(!0),r(S,null,b(Ke.value,t=>(m(),e(d,{key:t,label:t,value:t},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`,`onChange`]),t(f,{modelValue:o(R),"onUpdate:modelValue":i[2]||=e=>p(R)?R.value=e:null,placeholder:`时间范围`,clearable:``,style:{width:`130px`},onChange:o(We)},{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(C,{modelValue:o(z),"onUpdate:modelValue":i[3]||=e=>p(z)?z.value=e:null,type:`daterange`,"range-separator":`至`,"start-placeholder":`开始日期`,"end-placeholder":`结束日期`,"value-format":`YYYY-MM-DD`,style:{width:`260px`},onChange:Ge},null,8,[`modelValue`]),t(s,{loading:I.value,onClick:o(B)},{default:y(()=>[...i[11]||=[a(`刷新`,-1)]]),_:1},8,[`loading`,`onClick`])])])]),default:y(()=>[v(`div`,be,[v(`div`,xe,[v(`div`,Se,h(o(O)(F.value.total.total_tokens)),1),i[13]||=v(`div`,{class:`usage-label`},`总 Token`,-1)]),v(`div`,Ce,[v(`div`,we,h(o(O)(F.value.total.input_tokens)),1),i[14]||=v(`div`,{class:`usage-label`},`输入 Token`,-1)]),v(`div`,Te,[v(`div`,Ee,h(o(O)(F.value.total.output_tokens)),1),i[15]||=v(`div`,{class:`usage-label`},`输出 Token`,-1)]),v(`div`,De,[v(`div`,Oe,h(o(O)(F.value.total.cache_read_tokens)),1),i[16]||=v(`div`,{class:`usage-label`},`缓存读取`,-1)]),v(`div`,ke,[v(`div`,Ae,h(F.value.total.cache_rate==null?`-`:F.value.total.cache_rate+`%`),1),i[17]||=v(`div`,{class:`usage-label`},`缓存命中率`,-1)]),F.value.logStorageMB==null?_(``,!0):(m(),r(`div`,je,[v(`div`,Me,h(F.value.logStorageMB),1),i[18]||=v(`div`,{class:`usage-label`},`数据目录占用 (MB)`,-1)])),v(`div`,Ne,[v(`div`,Pe,h(o(N)(F.value.total.avg_duration)),1),i[19]||=v(`div`,{class:`usage-label`},`平均耗时`,-1)]),v(`div`,Fe,[v(`div`,{class:`usage-num blue`,title:o(k)},h(o(N)(F.value.total.avg_ttft)),9,Ie),i[20]||=v(`div`,{class:`usage-label`},`平均首 Token`,-1)]),v(`div`,Le,[v(`div`,{class:`usage-num green`,title:o(M)},h(o(A)(F.value.total.tps)),9,Re),i[21]||=v(`div`,{class:`usage-label`},`平均生成速度`,-1)])]),F.value.models?.length?(m(),r(`div`,ze,[i[22]||=v(`div`,{class:`section-title`},`模型用量`,-1),t(T,{data:F.value.models,stripe:``,class:`full-width`},{default:y(()=>[t(w,{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,Be)]),_:1}),t(w,{label:`调用次数`,width:`90`,align:`center`},{default:y(({row:e})=>[a(h(e.calls),1)]),_:1}),t(w,{label:`平均耗时`,width:`110`,align:`center`},{default:y(({row:e})=>[a(h(o(N)(e.avg_duration)),1)]),_:1}),t(w,{label:`速度`,width:`130`,align:`center`},{default:y(({row:e})=>[v(`div`,{title:o(M)},h(o(A)(e.tps)),9,Ve),e.avg_ttft==null?_(``,!0):(m(),r(`div`,{key:0,class:`cell-sub`,title:o(k)},` 首 `+h(o(N)(e.avg_ttft)),9,He))]),_:1}),t(w,{label:`总 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(O)(e.total_tokens)),1)]),_:1}),t(w,{label:`输入 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(O)(e.input_tokens)),1)]),_:1}),t(w,{label:`输出 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(O)(e.output_tokens)),1)]),_:1}),t(w,{label:`缓存读取`,width:`130`,align:`center`},{default:y(({row:e})=>[a(h(o(O)(e.cache_read_tokens)),1)]),_:1}),t(w,{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(E,{key:1,description:`暂无调用记录`,"image-size":60}))]),_:1})):_(``,!0)])}}});export{P 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 b,sn as ne,vt as x,w as S}from"./router-BzfmTCjF.js";import{t as C}from"./useManagerApi-lFkQleJX.js";import{t as w}from"./providers-BwuaO9o9.js";import{n as T,t as E}from"./useCopyToast-BpTqycuM.js";import{n as D,t as re}from"./useQuickRangeFilter-DmQyTw4A.js";import{f as O,n as k,p as A,r as j,t as M,u as N}from"./format-7jzqzMS_.js";x();function ie(e){let{loadError:t,run:n}=T(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(),x(),u();var ae={class:`flex-col-gap`},oe={class:`kv-grid`},se={class:`kv-label`},ce={class:`kv-value`},le=[`onClick`],ue={class:`kv-item kv-span-2`},de={class:`kv-value`},fe={key:1,class:`kv-unit`},pe={class:`kv-item`},me={class:`kv-value`},he={class:`kv-unit`},ge={class:`kv-item`},_e={class:`kv-value`},ve={class:`flex-between card-header-wrap`},ye={class:`flex-gap-8`},be={class:`usage-grid`},xe={class:`usage-cell`},Se={class:`usage-num orange`},Ce={class:`usage-cell`},we={class:`usage-num blue`},Te={class:`usage-cell`},Ee={class:`usage-num green`},De={class:`usage-cell`},Oe={class:`usage-num purple`},ke={class:`usage-cell`},Ae={class:`usage-num purple`},je={key:0,class:`usage-cell`},Me={class:`usage-num gray`},Ne={class:`usage-cell`},Pe={class:`usage-num blue`},Fe={class:`usage-cell`},Ie=[`title`],Le={class:`usage-cell`},Re=[`title`],ze={key:0},Be=[`onClick`],Ve=[`title`],He=[`title`],P=n({__name:`DashboardView`,setup(n){let l=w(),{copyWithToast:u}=E(),{loadError:x,track:T,retry:P}=ie(),Ue={local:`本机 API 地址`,lan:`局域网地址`,other:`API 地址`},F=c(null),I=c(!0),L=c(``),{rangeKey:R,dateRange:z,onRangeChange:We}=re(()=>B(),`today`),Ge=()=>{R.value=``,B()},Ke=i(()=>{let e=new Set;for(let t of l.suppliers)for(let n of t.models)e.add(n.modelName);if(F.value?.models)for(let t of F.value.models)e.add(t.model);return[...e].sort()}),qe=D(),B=T(async()=>{let e=qe();I.value=!0;try{let t=new URLSearchParams;L.value&&t.set(`model`,L.value),z.value?.length===2&&(t.set(`startDate`,z.value[0]),t.set(`endDate`,z.value[1]));let n=t.toString(),r=await f.get(`/api/usage${n?`?${n}`:``}`);if(!e())return;F.value=r}catch(t){if(!e())return;throw t}finally{e()&&(I.value=!1)}}),Je=D(),V=T(async()=>{let e=Je();try{await Promise.all([B(),l.loadProviders()])}catch(t){if(!e())return;throw t}finally{e()&&(I.value=!1)}}),Ye=()=>P(V),H=window.location.hostname,U=Number(window.location.port)||null,W=i(()=>j({protocol:window.location.protocol,hostname:H,port:U})),G=c(null),K=c(null),q=c(!1),J=c(!0),Y=c(Date.now()),X=c(null),Z=c([]),Q=i(()=>X.value??U),Xe=e=>j({protocol:`http:`,hostname:e,port:Q.value}),Ze=i(()=>H===`127.0.0.1`||H===`::1`||H===`localhost`?`local`:Z.value.includes(H)?`lan`:`other`),$=i(()=>Q.value?Z.value.map(Xe).filter(e=>e!==W.value):[]),Qe=i(()=>{let e=Q.value?Xe(`127.0.0.1`):``;return e!==``&&e!==W.value?e:``}),$e=i(()=>{let e=[];return Ze.value===`lan`?e.push({label:`局域网地址`,values:[W.value,...$.value]}):(e.push({label:Ue[Ze.value],values:[W.value]}),$.value.length>0&&e.push({label:`局域网地址`,values:$.value})),Qe.value!==``&&e.push({label:`本机 API 地址`,values:[Qe.value]}),e.map((t,n)=>({...t,span2:e.length%2==1&&n===e.length-1}))}),et=async()=>{let[e,t]=await Promise.allSettled([C.processes(),f.get(`/api/status`)]);if(J.value=!1,e.status===`fulfilled`&&(G.value=e.value[0]??null),t.status===`rejected`){K.value=null,q.value=!0;return}let n=t.value?.masterKey;K.value=typeof n==`string`?n:null,q.value=typeof n!=`string`;let r=t.value?.listenPort;X.value=typeof r==`number`&&r>0?r:null;let i=t.value?.lanAddresses;Z.value=Array.isArray(i)?i.filter(e=>typeof e==`string`):[],Y.value=Date.now()},tt=e=>{if(!e.startedAt)return`-`;let t=Math.max(0,Math.floor((Y.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(` `)},nt=i(()=>q.value?`获取失败,请刷新重试`:K.value===null?`-`:`未设置(/v1 免鉴权)`),rt;return d(()=>{V(),et(),rt=window.setInterval(et,1e4)}),s(()=>window.clearInterval(rt)),(n,i)=>{let s=g(`el-button`),c=g(`el-alert`),l=g(`el-card`),d=g(`el-option`),f=g(`el-select`),C=g(`el-date-picker`),w=g(`el-table-column`),T=g(`el-table`),E=g(`el-empty`),D=ee(`loading`);return m(),r(`div`,ae,[o(x)?(m(),e(c,{key:0,title:o(x),type:`error`,"show-icon":``,closable:!1},{default:y(()=>[t(s,{size:`small`,onClick:Ye},{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`,oe,[(m(!0),r(S,null,b($e.value,e=>(m(),r(`div`,{key:e.label+e.values[0],class:ne([`kv-item`,{"kv-span-2":e.span2}])},[v(`div`,se,h(e.label),1),v(`div`,ce,[(m(!0),r(S,null,b(e.values,e=>(m(),r(`div`,{key:e},[v(`span`,{class:`copy-text`,onClick:t=>o(u)(e)},h(e),9,le)]))),128))])],2))),128)),v(`div`,ue,[i[6]||=v(`div`,{class:`kv-label`},`API 密钥`,-1),v(`div`,de,[K.value?(m(),r(`span`,{key:0,class:`copy-text`,onClick:i[0]||=e=>o(u)(K.value)},h(K.value),1)):_(``,!0),K.value?(m(),r(`span`,fe,`(/v1 需 Bearer 认证)`)):(m(),r(S,{key:2},[a(h(nt.value),1)],64))])]),v(`div`,pe,[i[9]||=v(`div`,{class:`kv-label`},`运行状态`,-1),v(`div`,me,[G.value?(m(),r(S,{key:0},[i[7]||=v(`span`,{class:`status-dot running`},null,-1),i[8]||=a(`运行中 `,-1),v(`span`,he,`PID `+h(G.value.pid??`-`),1)],64)):(m(),r(S,{key:1},[a(`-`)],64))])]),v(`div`,ge,[i[10]||=v(`div`,{class:`kv-label`},`运行时长`,-1),v(`div`,_e,h(G.value?tt(G.value):`-`),1)])])),[[D,I.value||J.value]])]),_:1}),F.value?(m(),e(l,{key:1,shadow:`never`},{header:y(()=>[v(`div`,ve,[i[12]||=v(`span`,{class:`fw-600`},`用量统计`,-1),v(`div`,ye,[t(f,{modelValue:L.value,"onUpdate:modelValue":i[1]||=e=>L.value=e,placeholder:`全部模型`,clearable:``,filterable:``,style:{width:`220px`},onChange:o(B)},{default:y(()=>[(m(!0),r(S,null,b(Ke.value,t=>(m(),e(d,{key:t,label:t,value:t},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`,`onChange`]),t(f,{modelValue:o(R),"onUpdate:modelValue":i[2]||=e=>p(R)?R.value=e:null,placeholder:`时间范围`,clearable:``,style:{width:`130px`},onChange:o(We)},{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(C,{modelValue:o(z),"onUpdate:modelValue":i[3]||=e=>p(z)?z.value=e:null,type:`daterange`,"range-separator":`至`,"start-placeholder":`开始日期`,"end-placeholder":`结束日期`,"value-format":`YYYY-MM-DD`,style:{width:`260px`},onChange:Ge},null,8,[`modelValue`]),t(s,{loading:I.value,onClick:o(B)},{default:y(()=>[...i[11]||=[a(`刷新`,-1)]]),_:1},8,[`loading`,`onClick`])])])]),default:y(()=>[v(`div`,be,[v(`div`,xe,[v(`div`,Se,h(o(O)(F.value.total.total_tokens)),1),i[13]||=v(`div`,{class:`usage-label`},`总 Token`,-1)]),v(`div`,Ce,[v(`div`,we,h(o(O)(F.value.total.input_tokens)),1),i[14]||=v(`div`,{class:`usage-label`},`输入 Token`,-1)]),v(`div`,Te,[v(`div`,Ee,h(o(O)(F.value.total.output_tokens)),1),i[15]||=v(`div`,{class:`usage-label`},`输出 Token`,-1)]),v(`div`,De,[v(`div`,Oe,h(o(O)(F.value.total.cache_read_tokens)),1),i[16]||=v(`div`,{class:`usage-label`},`缓存读取`,-1)]),v(`div`,ke,[v(`div`,Ae,h(F.value.total.cache_rate==null?`-`:F.value.total.cache_rate+`%`),1),i[17]||=v(`div`,{class:`usage-label`},`缓存命中率`,-1)]),F.value.logStorageMB==null?_(``,!0):(m(),r(`div`,je,[v(`div`,Me,h(F.value.logStorageMB),1),i[18]||=v(`div`,{class:`usage-label`},`数据目录占用 (MB)`,-1)])),v(`div`,Ne,[v(`div`,Pe,h(o(N)(F.value.total.avg_duration)),1),i[19]||=v(`div`,{class:`usage-label`},`平均耗时`,-1)]),v(`div`,Fe,[v(`div`,{class:`usage-num blue`,title:o(k)},h(o(N)(F.value.total.avg_ttft)),9,Ie),i[20]||=v(`div`,{class:`usage-label`},`平均首 Token`,-1)]),v(`div`,Le,[v(`div`,{class:`usage-num green`,title:o(M)},h(o(A)(F.value.total.tps)),9,Re),i[21]||=v(`div`,{class:`usage-label`},`平均生成速度`,-1)])]),F.value.models?.length?(m(),r(`div`,ze,[i[22]||=v(`div`,{class:`section-title`},`模型用量`,-1),t(T,{data:F.value.models,stripe:``,class:`full-width`},{default:y(()=>[t(w,{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,Be)]),_:1}),t(w,{label:`调用次数`,width:`90`,align:`center`},{default:y(({row:e})=>[a(h(e.calls),1)]),_:1}),t(w,{label:`平均耗时`,width:`110`,align:`center`},{default:y(({row:e})=>[a(h(o(N)(e.avg_duration)),1)]),_:1}),t(w,{label:`速度`,width:`130`,align:`center`},{default:y(({row:e})=>[v(`div`,{title:o(M)},h(o(A)(e.tps)),9,Ve),e.avg_ttft==null?_(``,!0):(m(),r(`div`,{key:0,class:`cell-sub`,title:o(k)},` 首 `+h(o(N)(e.avg_ttft)),9,He))]),_:1}),t(w,{label:`总 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(O)(e.total_tokens)),1)]),_:1}),t(w,{label:`输入 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(O)(e.input_tokens)),1)]),_:1}),t(w,{label:`输出 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(O)(e.output_tokens)),1)]),_:1}),t(w,{label:`缓存读取`,width:`130`,align:`center`},{default:y(({row:e})=>[a(h(o(O)(e.cache_read_tokens)),1)]),_:1}),t(w,{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(E,{key:1,description:`暂无调用记录`,"image-size":60}))]),_:1})):_(``,!0)])}}});export{P as default};
@@ -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-Daxct41S.js";import{m as D}from"./message-B022-tc2.js";import{n as O,t as k}from"./index-D6ydfwRk.js";import{n as A,t as j}from"./useManagerApi-DdgACgsq.js";import{t as M}from"./useToast-nQZ8k6t7.js";import{t as N}from"./updateNote-CttDt8SZ.js";c(),l(),T();var P={class:`check-body`},F={class:`version-row`},I={class:`version-row`},L={class:`muted-sm`},R=k(n({__name:`UpdateCheckDialog`,props:{modelValue:{type:Boolean,default:!1},modelModifiers:{}},emits:[`update:modelValue`],setup(n){let{toast:o}=M(),c=b(n,`modelValue`),l=s(!1),u=s(!1),y=s(null),S=s(null),C=i(()=>h.value?.buildSource===`local`),w=s(null),T=s(null),D=null,k=()=>D?.abort(),R=e=>new Date(e).toLocaleString(),z=e=>`https://www.npmjs.com/package/ezllm/v/${e}`,B=async()=>{S.value=null,w.value=null,T.value=null,l.value=!0;try{let e=await j.update();if(y.value=e,!e.supported)return;S.value=await j.checkUpdate()}catch(e){w.value=e.message||`检查更新失败`}finally{l.value=!1}},V=async()=>{if(!S.value)return;let e=S.value.latestVersion;try{await O.confirm(`发现新版本 ${e}:更新需在终端执行「npx ezllm update」完成(管理台不再自动安装)。`,`更新方式`,{confirmButtonText:`查看指引`,cancelButtonText:`取消`,type:`info`})}catch{return}u.value=!0;let t=new AbortController;D=t;try{let e=await j.update(),n=await j.applyUpdate();if(!n.updated){n.hasUpdate?T.value=`发现新版本 ${n.toVersion}(当前 ${n.fromVersion}):请在终端执行 npx ezllm update 完成更新`:(T.value=`已是最新版本 ${n.fromVersion}`,S.value={hasUpdate:!1,currentVersion:n.fromVersion,latestVersion:n.fromVersion,checkedAt:Date.now()});return}T.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?(o(`已更新到 ${r.toVersion}`,`success`),T.value=`已更新 ${r.fromVersion} → ${r.toVersion},服务已在新版本上运行。`,S.value={hasUpdate:!1,currentVersion:r.toVersion,latestVersion:r.toVersion,checkedAt:Date.now()}):r?.error?(o(`更新失败:${r.error}`,`error`),T.value=N(r.error)):T.value=`更新仍在进行(安装耗时较长):稍后刷新页面查看最新状态。`}catch(e){o(e.message||`更新失败`,`error`)}finally{u.value=!1,D===t&&(D=null)}};return(n,i)=>{let o=g(`el-alert`),s=g(`el-tag`),h=g(`el-link`),b=g(`el-button`),D=g(`el-dialog`),O=d(`loading`);return f(),e(D,{modelValue:c.value,"onUpdate:modelValue":i[2]||=e=>c.value=e,title:`检查更新`,width:`420px`,"close-on-click-modal":!u.value,onOpen:B,onClose:k},{footer:x(()=>[S.value?.hasUpdate?(f(),e(b,{key:0,type:`primary`,loading:u.value,onClick:V},{default:x(()=>[a(p(u.value?`处理中...`:`查看更新方式`),1)]),_:1},8,[`loading`])):_(``,!0),t(b,{onClick:i[1]||=e=>c.value=!1},{default:x(()=>[...i[11]||=[a(`关闭`,-1)]]),_:1})]),default:x(()=>[m((f(),r(`div`,P,[y.value&&!y.value.supported?(f(),e(o,{key:0,title:`当前为源码运行模式,更新功能不可用`,type:`info`,"show-icon":``,closable:!1},{default:x(()=>[...i[3]||=[v(`div`,{class:`alert-hint`},[a(` 仅通过 npx ezllm install 装配的实例支持更新检查。本地开发用仓库里的 `),v(`code`,null,`pnpm upgrade:local`),a(` 更新运行中的服务。 `)],-1)]]),_:1})):S.value?(f(),r(E,{key:1},[v(`div`,F,[i[5]||=v(`span`,{class:`version-label`},`当前版本`,-1),t(s,{size:`small`},{default:x(()=>[a(p(S.value.currentVersion),1)]),_:1}),C.value?(f(),e(s,{key:0,type:`warning`,size:`small`,"disable-transitions":``},{default:x(()=>[...i[4]||=[a(`本地构建`,-1)]]),_:1})):_(``,!0)]),v(`div`,I,[i[6]||=v(`span`,{class:`version-label`},`最新版本`,-1),t(s,{type:S.value.hasUpdate?`warning`:`success`,size:`small`,"disable-transitions":``},{default:x(()=>[a(p(S.value.latestVersion),1)]),_:1},8,[`type`])]),t(o,{title:S.value.hasUpdate?`发现新版本 ${S.value.latestVersion}(当前 ${S.value.currentVersion})`:`已是最新版本 ${S.value.currentVersion}`,type:S.value.hasUpdate?`warning`:`success`,"show-icon":``,closable:!1,class:`mt-12`},null,8,[`title`,`type`]),v(`div`,L,[a(` 检查时间:`+p(R(S.value.checkedAt))+` `,1),S.value.hasUpdate?(f(),r(E,{key:0},[i[8]||=a(` · `,-1),t(h,{type:`primary`,href:z(S.value.latestVersion),target:`_blank`},{default:x(()=>[...i[7]||=[a(`在 npm 查看该版本`,-1)]]),_:1},8,[`href`])],64)):_(``,!0)])],64)):!l.value&&w.value?(f(),e(o,{key:2,title:w.value,type:`error`,"show-icon":``,closable:!1},{default:x(()=>[i[10]||=v(`div`,{class:`alert-hint`},` 检查需访问 npm 源,可能是网络不可达或版本号解析失败;稍后重试即可。 `,-1),t(b,{size:`small`,class:`mt-8`,onClick:B},{default:x(()=>[...i[9]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):_(``,!0)])),[[O,l.value]]),T.value?(f(),e(o,{key:0,title:T.value,type:`info`,"show-icon":``,class:`mt-12`,onClose:i[0]||=e=>T.value=null},null,8,[`title`])):_(``,!0)]),_:1},8,[`modelValue`,`close-on-click-modal`])}}}),[[`__scopeId`,`data-v-97a70069`]]);c(),l(),T();var z={class:`layout`},B=[`title`],V={key:0,class:`header-version-tag`},H={class:`header-nav`},U={class:`header-actions`},W={class:`user-chip`},G={class:`user-avatar`},K={class:`user-name`},q={class:`main`},J={class:`page`},Y=k(n({__name:`LayoutView`,setup(n){let c=y(),l=w(),d=s(!1);u(()=>{S()});let m=i(()=>h.value?.version||``),b=i(()=>h.value?.buildSource===`local`),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`,z,[t(S,{class:`header`},{default:x(()=>[i[10]||=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`,V,`本地构建`)):_(``,!0)],8,B)):_(``,!0),v(`nav`,H,[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:`/plugins`},{default:x(()=>[...i[5]||=[a(`插件`,-1)]]),_:1}),t(s,{index:`/logs`},{default:x(()=>[...i[6]||=[a(`日志`,-1)]]),_:1}),t(s,{index:`/settings`},{default:x(()=>[...i[7]||=[a(`设置`,-1)]]),_:1})]),_:1},8,[`default-active`])]),v(`div`,U,[t(y,{trigger:`click`,onCommand:A,class:`ml-12`},{dropdown:x(()=>[t(h,null,{default:x(()=>[t(u,{command:`check-update`},{default:x(()=>[...i[8]||=[a(`检查更新`,-1)]]),_:1}),E.value?(f(),e(u,{key:0,command:`logout`,divided:``},{default:x(()=>[...i[9]||=[a(`退出`,-1)]]),_:1})):_(``,!0)]),_:1})]),default:x(()=>[v(`div`,W,[v(`span`,G,p(O.value.charAt(0).toUpperCase()),1),v(`span`,K,p(O.value),1),t(l,{class:`el-icon--right`},{default:x(()=>[t(o(D))]),_:1})])]),_:1})])]),_:1}),v(`main`,q,[v(`div`,J,[t(C)])]),t(R,{modelValue:d.value,"onUpdate:modelValue":i[0]||=e=>d.value=e},null,8,[`modelValue`])])}}}),[[`__scopeId`,`data-v-4e7e0e0d`]]);export{Y 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-BzfmTCjF.js";import{m as D}from"./message-Cp_GAwQs.js";import{n as O,t as k}from"./index-D2JhqxaS.js";import{n as A,t as j}from"./useManagerApi-lFkQleJX.js";import{t as M}from"./useToast-D3xB24vj.js";import{t as N}from"./updateNote-CttDt8SZ.js";c(),l(),T();var P={class:`check-body`},F={class:`version-row`},I={class:`version-row`},L={class:`muted-sm`},R=k(n({__name:`UpdateCheckDialog`,props:{modelValue:{type:Boolean,default:!1},modelModifiers:{}},emits:[`update:modelValue`],setup(n){let{toast:o}=M(),c=b(n,`modelValue`),l=s(!1),u=s(!1),y=s(null),S=s(null),C=i(()=>h.value?.buildSource===`local`),w=s(null),T=s(null),D=null,k=()=>D?.abort(),R=e=>new Date(e).toLocaleString(),z=e=>`https://www.npmjs.com/package/ezllm/v/${e}`,B=async()=>{S.value=null,w.value=null,T.value=null,l.value=!0;try{let e=await j.update();if(y.value=e,!e.supported)return;S.value=await j.checkUpdate()}catch(e){w.value=e.message||`检查更新失败`}finally{l.value=!1}},V=async()=>{if(!S.value)return;let e=S.value.latestVersion;try{await O.confirm(`发现新版本 ${e}:更新需在终端执行「npx ezllm update」完成(管理台不再自动安装)。`,`更新方式`,{confirmButtonText:`查看指引`,cancelButtonText:`取消`,type:`info`})}catch{return}u.value=!0;let t=new AbortController;D=t;try{let e=await j.update(),n=await j.applyUpdate();if(!n.updated){n.hasUpdate?T.value=`发现新版本 ${n.toVersion}(当前 ${n.fromVersion}):请在终端执行 npx ezllm update 完成更新`:(T.value=`已是最新版本 ${n.fromVersion}`,S.value={hasUpdate:!1,currentVersion:n.fromVersion,latestVersion:n.fromVersion,checkedAt:Date.now()});return}T.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?(o(`已更新到 ${r.toVersion}`,`success`),T.value=`已更新 ${r.fromVersion} → ${r.toVersion},服务已在新版本上运行。`,S.value={hasUpdate:!1,currentVersion:r.toVersion,latestVersion:r.toVersion,checkedAt:Date.now()}):r?.error?(o(`更新失败:${r.error}`,`error`),T.value=N(r.error)):T.value=`更新仍在进行(安装耗时较长):稍后刷新页面查看最新状态。`}catch(e){o(e.message||`更新失败`,`error`)}finally{u.value=!1,D===t&&(D=null)}};return(n,i)=>{let o=g(`el-alert`),s=g(`el-tag`),h=g(`el-link`),b=g(`el-button`),D=g(`el-dialog`),O=d(`loading`);return f(),e(D,{modelValue:c.value,"onUpdate:modelValue":i[2]||=e=>c.value=e,title:`检查更新`,width:`420px`,"close-on-click-modal":!u.value,onOpen:B,onClose:k},{footer:x(()=>[S.value?.hasUpdate?(f(),e(b,{key:0,type:`primary`,loading:u.value,onClick:V},{default:x(()=>[a(p(u.value?`处理中...`:`查看更新方式`),1)]),_:1},8,[`loading`])):_(``,!0),t(b,{onClick:i[1]||=e=>c.value=!1},{default:x(()=>[...i[11]||=[a(`关闭`,-1)]]),_:1})]),default:x(()=>[m((f(),r(`div`,P,[y.value&&!y.value.supported?(f(),e(o,{key:0,title:`当前为源码运行模式,更新功能不可用`,type:`info`,"show-icon":``,closable:!1},{default:x(()=>[...i[3]||=[v(`div`,{class:`alert-hint`},[a(` 仅通过 npx ezllm install 装配的实例支持更新检查。本地开发用仓库里的 `),v(`code`,null,`pnpm upgrade:local`),a(` 更新运行中的服务。 `)],-1)]]),_:1})):S.value?(f(),r(E,{key:1},[v(`div`,F,[i[5]||=v(`span`,{class:`version-label`},`当前版本`,-1),t(s,{size:`small`},{default:x(()=>[a(p(S.value.currentVersion),1)]),_:1}),C.value?(f(),e(s,{key:0,type:`warning`,size:`small`,"disable-transitions":``},{default:x(()=>[...i[4]||=[a(`本地构建`,-1)]]),_:1})):_(``,!0)]),v(`div`,I,[i[6]||=v(`span`,{class:`version-label`},`最新版本`,-1),t(s,{type:S.value.hasUpdate?`warning`:`success`,size:`small`,"disable-transitions":``},{default:x(()=>[a(p(S.value.latestVersion),1)]),_:1},8,[`type`])]),t(o,{title:S.value.hasUpdate?`发现新版本 ${S.value.latestVersion}(当前 ${S.value.currentVersion})`:`已是最新版本 ${S.value.currentVersion}`,type:S.value.hasUpdate?`warning`:`success`,"show-icon":``,closable:!1,class:`mt-12`},null,8,[`title`,`type`]),v(`div`,L,[a(` 检查时间:`+p(R(S.value.checkedAt))+` `,1),S.value.hasUpdate?(f(),r(E,{key:0},[i[8]||=a(` · `,-1),t(h,{type:`primary`,href:z(S.value.latestVersion),target:`_blank`},{default:x(()=>[...i[7]||=[a(`在 npm 查看该版本`,-1)]]),_:1},8,[`href`])],64)):_(``,!0)])],64)):!l.value&&w.value?(f(),e(o,{key:2,title:w.value,type:`error`,"show-icon":``,closable:!1},{default:x(()=>[i[10]||=v(`div`,{class:`alert-hint`},` 检查需访问 npm 源,可能是网络不可达或版本号解析失败;稍后重试即可。 `,-1),t(b,{size:`small`,class:`mt-8`,onClick:B},{default:x(()=>[...i[9]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):_(``,!0)])),[[O,l.value]]),T.value?(f(),e(o,{key:0,title:T.value,type:`info`,"show-icon":``,class:`mt-12`,onClose:i[0]||=e=>T.value=null},null,8,[`title`])):_(``,!0)]),_:1},8,[`modelValue`,`close-on-click-modal`])}}}),[[`__scopeId`,`data-v-97a70069`]]);c(),l(),T();var z={class:`layout`},B=[`title`],V={key:0,class:`header-version-tag`},H={class:`header-nav`},U={class:`header-actions`},W={class:`user-chip`},G={class:`user-avatar`},K={class:`user-name`},q={class:`main`},J={class:`page`},Y=k(n({__name:`LayoutView`,setup(n){let c=y(),l=w(),d=s(!1);u(()=>{S()});let m=i(()=>h.value?.version||``),b=i(()=>h.value?.buildSource===`local`),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`,z,[t(S,{class:`header`},{default:x(()=>[i[10]||=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`,V,`本地构建`)):_(``,!0)],8,B)):_(``,!0),v(`nav`,H,[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:`/plugins`},{default:x(()=>[...i[5]||=[a(`插件`,-1)]]),_:1}),t(s,{index:`/logs`},{default:x(()=>[...i[6]||=[a(`日志`,-1)]]),_:1}),t(s,{index:`/settings`},{default:x(()=>[...i[7]||=[a(`设置`,-1)]]),_:1})]),_:1},8,[`default-active`])]),v(`div`,U,[t(y,{trigger:`click`,onCommand:A,class:`ml-12`},{dropdown:x(()=>[t(h,null,{default:x(()=>[t(u,{command:`check-update`},{default:x(()=>[...i[8]||=[a(`检查更新`,-1)]]),_:1}),E.value?(f(),e(u,{key:0,command:`logout`,divided:``},{default:x(()=>[...i[9]||=[a(`退出`,-1)]]),_:1})):_(``,!0)]),_:1})]),default:x(()=>[v(`div`,W,[v(`span`,G,p(O.value.charAt(0).toUpperCase()),1),v(`span`,K,p(O.value),1),t(l,{class:`el-icon--right`},{default:x(()=>[t(o(D))]),_:1})])]),_:1})])]),_:1}),v(`main`,q,[v(`div`,J,[t(C)])]),t(R,{modelValue:d.value,"onUpdate:modelValue":i[0]||=e=>d.value=e},null,8,[`modelValue`])])}}}),[[`__scopeId`,`data-v-4e7e0e0d`]]);export{Y 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-Daxct41S.js";import{t as y}from"./index-D6ydfwRk.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-BzfmTCjF.js";import{t as y}from"./index-D2JhqxaS.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,4 +1,4 @@
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-Daxct41S.js";import{R as k,S as te}from"./message-B022-tc2.js";import{n as A,t as j}from"./index-D6ydfwRk.js";import{t as M}from"./providers-C6QKdfzy.js";import{n as N,t as P}from"./useCopyToast-0dz9T4-H.js";import{t as ne}from"./useToast-nQZ8k6t7.js";import{n as F,t as re}from"./useQuickRangeFilter-D8oTOMUp.js";import{S as I,_ as L,a as R,c as z,f as B,g as V,h as H,i as ie,l as U,m as W,n as ae,o as oe,p as se,s as G,t as ce,u as K,x as le}from"./format-7jzqzMS_.js";u(),T(),d();var ue={class:`detail-content`},de={key:0,class:`ip-link`},q={class:`ip-pop`},fe={class:`ip-pop-row`},J={key:0,class:`ip-pop-row`},Y={key:1,class:`ip-pop-error`},X={key:2},pe=[`href`],me={key:1},he={key:1},ge=[`title`],_e=[`title`],ve={class:`error-text`},ye={class:`pane-bar`},be={class:`json-block`},xe={class:`pane-bar`},Se={class:`json-block`},Z={class:`pane-bar`},Ce={class:`json-block`},Q={class:`pane-bar`},we={class:`json-block`},Te={class:`pane-bar`},$={class:`json-block`},Ee={class:`pane-bar`},De={class:`json-block`},Oe={class:`pane-bar`},ke={class:`json-block`},Ae={class:`pane-bar`},je={class:`json-block`},Me=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=F(),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(()=>W(m.value?.response?.inbound_request)),j=a(()=>W(m.value?.response?.upstream_request)),M=a(()=>V(m.value?.response?.upstream_response_text)),ne=a(()=>(m.value?.response?.upstream_stream_frames||[]).join(`
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-BzfmTCjF.js";import{R as k,S as te}from"./message-Cp_GAwQs.js";import{n as A,t as j}from"./index-D2JhqxaS.js";import{t as M}from"./providers-BwuaO9o9.js";import{n as N,t as P}from"./useCopyToast-BpTqycuM.js";import{t as ne}from"./useToast-D3xB24vj.js";import{n as F,t as re}from"./useQuickRangeFilter-DmQyTw4A.js";import{S as I,_ as L,a as R,c as z,f as B,g as V,h as H,i as ie,l as U,m as W,n as ae,o as oe,p as se,s as G,t as ce,u as K,x as le}from"./format-7jzqzMS_.js";u(),T(),d();var ue={class:`detail-content`},de={key:0,class:`ip-link`},q={class:`ip-pop`},fe={class:`ip-pop-row`},J={key:0,class:`ip-pop-row`},Y={key:1,class:`ip-pop-error`},X={key:2},pe=[`href`],me={key:1},he={key:1},ge=[`title`],_e=[`title`],ve={class:`error-text`},ye={class:`pane-bar`},be={class:`json-block`},xe={class:`pane-bar`},Se={class:`json-block`},Z={class:`pane-bar`},Ce={class:`json-block`},Q={class:`pane-bar`},we={class:`json-block`},Te={class:`pane-bar`},$={class:`json-block`},Ee={class:`pane-bar`},De={class:`json-block`},Oe={class:`pane-bar`},ke={class:`json-block`},Ae={class:`pane-bar`},je={class:`json-block`},Me=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=F(),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(()=>W(m.value?.response?.inbound_request)),j=a(()=>W(m.value?.response?.upstream_request)),M=a(()=>V(m.value?.response?.upstream_response_text)),ne=a(()=>(m.value?.response?.upstream_stream_frames||[]).join(`
2
2
 
3
3
  `)),re=a(()=>W(m.value?.response?.client_response)),L=a(()=>(m.value?.response?.client_stream_frames||[]).join(`
4
4
 
@@ -1,4 +1,4 @@
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-Daxct41S.js";import{W as S}from"./message-B022-tc2.js";import{n as C,t as w}from"./index-D6ydfwRk.js";import{t as T}from"./useManagerApi-DdgACgsq.js";import{n as E,t as D}from"./useCopyToast-0dz9T4-H.js";import{t as O}from"./useToast-nQZ8k6t7.js";import{h as k}from"./format-7jzqzMS_.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(`
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-BzfmTCjF.js";import{W as S}from"./message-Cp_GAwQs.js";import{n as C,t as w}from"./index-D2JhqxaS.js";import{t as T}from"./useManagerApi-lFkQleJX.js";import{n as E,t as D}from"./useCopyToast-BpTqycuM.js";import{t as O}from"./useToast-D3xB24vj.js";import{h as k}from"./format-7jzqzMS_.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
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
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
@@ -0,0 +1,2 @@
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 ee,et as u,fn as d,it as f,j as p,k as m,m as te,mt as h,nt as g,s as _,vt as v,w as y,x as ne}from"./router-BzfmTCjF.js";import{W as re}from"./message-Cp_GAwQs.js";import{n as b,t as x}from"./index-D2JhqxaS.js";import{t as ie}from"./useManagerApi-lFkQleJX.js";import{t as S}from"./src-DLq1gsLr.js";import{t as ae}from"./useToast-D3xB24vj.js";async function C(e,t={}){return await _.post(`/api/fetch`,{url:e,...t})}async function w(e,t){if(e.binary)throw Error(`${t} 返回二进制内容(${e.contentType||`无 content-type`}),不是 JSON`);let n=e.body;if(e.status<200||e.status>=300){let t=(n??``).trim().slice(0,300);throw Error(`上游返回 HTTP ${String(e.status)}${t===``?``:`:${t}`}`)}if(n===null||n.trim()===``)throw Error(`上游返回空响应体(HTTP ${String(e.status)},${e.contentType||`无 content-type`})`);try{return JSON.parse(n)}catch{throw Error(`上游响应不是 JSON(HTTP ${String(e.status)},${e.contentType||`无 content-type`}):`+n.trim().slice(0,300))}}function T(e,t){return`http://127.0.0.1:${String(e)}${t.startsWith(`/`)?t:`/${t}`}`}async function E(e,t={}){return await w(await C(e,{method:`GET`,...t}),e)}async function D(e,t,n=`POST`){return await w(await C(e,{method:n,body:t}),e)}async function O(e){return await w(await C(e,{method:`DELETE`}),e)}v();var k=`https://raw.githubusercontent.com/magpie-community/plugins/main/registry.json`,A=[`https://gh-proxy.com/${k}`,`https://ghfast.top/${k}`,k],oe=1e4,se=`plugin_market_cache`,j=1,ce=216e5,le=36e5,ue=[`provider`];function M(){try{let e=localStorage.getItem(se);if(e===null)return null;let t=JSON.parse(e);if(t.version!==j||!Array.isArray(t.entries))return null;let n=t.fetchedAt;return n===void 0||typeof n.at!=`number`?null:{version:j,entries:t.entries.filter(L),fetchedAt:n}}catch{return null}}function N(e,t){try{let n={version:j,entries:e,fetchedAt:t};localStorage.setItem(se,JSON.stringify(n))}catch{}}function P(e){return typeof e==`string`&&e.trim()!==``?e.trim():null}function F(e){if(typeof e!=`object`||!e||Array.isArray(e))return null;let t=e;return P(t.zh)??P(t.en)}function I(e){switch(e){case`provider`:case`middleware`:case`agent`:case`tools`:case`page`:return e;default:return`provider`}}function de(e){return ue.includes(e)}function L(e){if(typeof e!=`object`||!e)return!1;let t=e.kind;return typeof t==`string`&&de(t)}function R(e){let t=P(e.package);if(t===null)return null;let n=Array.isArray(e.providers)?e.providers.filter(e=>typeof e==`string`):[];return{package:t,name:P(e.name)??t,icon:P(e.icon),providers:n,community:P(e.community),summary:F(e.summary),kind:I(e.kind),replaces:P(e.replaces),version:null,license:null,description:null,homepage:null,weeklyDownloads:null}}var z=new Map,B=new Map;async function fe(e){let t=z.get(e);if(t!==void 0&&Date.now()-t.at<le)return t.meta;try{let t=await E(`https://registry.npmjs.org/${encodeURIComponent(e)}`),n={version:P(t[`dist-tags`]?.latest),license:P(t.license),description:P(t.description),homepage:P(t.homepage)};return z.set(e,{at:Date.now(),meta:n}),n}catch{return{version:null,license:null,description:null,homepage:null}}}async function pe(e){let t=B.get(e);if(t!==void 0&&Date.now()-t.at<le)return t.downloads;try{let t=await E(`https://api.npmjs.org/downloads/point/last-week/${encodeURIComponent(e)}`),n=typeof t.downloads==`number`?t.downloads:null;return B.set(e,{at:Date.now(),downloads:n}),n}catch{return null}}async function me(){let e=[];for(let t of A)try{let e=await E(t,{timeoutMs:oe});return t!==A[0]&&S(`[plugin-market] 清单改由备用源取到:${t}`),{registry:e,source:t}}catch(n){let r=n instanceof Error?n.message:String(n);e.push(`${t} → ${r}`)}throw Error(`插件清单取不到(已试 ${String(A.length)} 个源):\n${e.join(`
2
+ `)}`)}async function he(e){let{registry:t,source:n}=await me(),r=t.plugins;if(!Array.isArray(r))throw Error(`清单格式不是预期形状(缺 plugins 数组):${k}`);let i=r.map(e=>typeof e==`object`&&e?R(e):null).filter(L).sort((e,t)=>e.package.localeCompare(t.package)),a=0;return await Promise.all(i.map(async t=>{let[n,r]=await Promise.all([fe(t.package),pe(t.package)]);Object.assign(t,n,{weeklyDownloads:r}),a+=1,e?.(a,i.length)})),{entries:i,source:n}}var V=s([]),H=s(!1),U=s(null),ge=s({loaded:0,total:0}),W=s(null),G=s(!1),K=null;function q(e,t){JSON.stringify(e)!==JSON.stringify(V.value)&&(V.value=e),W.value=t,N(e,t)}async function _e(e={}){let t=e.force===!0,n=V.value.length===0?M():null;n!==null&&(V.value=n.entries,W.value=n.fetchedAt);let r=V.value.length>0,i=W.value,a=i!==null&&Date.now()-i.at<ce;if(!(!t&&r&&a)){if(K!==null){if(t)await K;else return}if(t||!r){H.value=!0,G.value=!1,ge.value={loaded:0,total:0};try{let e=await he((e,t)=>{ge.value={loaded:e,total:t}});q(e.entries,{source:e.source,at:Date.now()}),U.value=null}catch(e){U.value=`插件市场清单加载失败:${e instanceof Error?e.message:String(e)}`}finally{H.value=!1}return}G.value=!0,K=(async()=>{try{let e=await he();q(e.entries,{source:e.source,at:Date.now()}),U.value=null,G.value=!1}catch(e){S(`[plugin-market] 后台刷新失败,继续用缓存:${e instanceof Error?e.message:String(e)}`)}finally{K=null}})()}}function ve(){return{entries:V,loading:H,marketError:U,progress:ge,fetchedAt:W,stale:G,loadMarket:_e}}c(),v(),l(),te();var ye={class:`page-head`},be={class:`page-head-actions`},xe={class:`flex-between`},Se={class:`muted-sm`},Ce={key:0,class:`loading-block`},we={key:1,class:`loading-block`},Te={key:2,class:`plugin-grid`},Ee={class:`card-top`},De={class:`plugin-icon`},Oe=[`src`,`alt`,`onError`],ke={key:1},Ae={class:`plugin-titles`},je=[`title`],Me={class:`plugin-tags`},Ne={class:`plugin-action`},Pe=[`title`],Fe={class:`plugin-meta`},Ie={key:0},Le={key:1,class:`mono`},Re={key:2,class:`muted-disabled`},ze={class:`mono`},Be={key:0,class:`muted-sm`},Ve={class:`mono`},He={class:`mono`},Ue={class:`mono muted-12`},We={class:`method-list`},Ge={class:`muted-sm`},Ke={key:0,class:`muted-sm`},qe={class:`muted-sm`},Je={class:`muted-sm`},Ye={key:0,class:`mt-8`},Xe=[`href`],Ze={key:2,class:`muted-sm mt-8`},Qe=x(n({__name:`PluginsView`,setup(n){let{toast:c}=ae(),l=s(!0),te=s(`服务未由 ezllm 主进程托管(源码运行模式);请用 ezllm 启动服务`),_=s(!1),v=s(!1),x=s(null),S=s(!1),C=s(!0),w=s(!1),{entries:k,loading:A,marketError:oe,progress:se,fetchedAt:j,stale:ce,loadMarket:le}=ve(),ue=s(new Set),M=s([]),N=s(null),P=s(!1),F=s(``),I=s(!1),de=s(!1),L=s({}),R=s(!1),z=s(!0),B=i(()=>v.value&&x.value!==null),fe=e=>M.value.some(t=>t.package===e.package),pe=e=>e.icon===null||ue.value.has(e.package)?null:/^https?:\/\//i.test(e.icon)?e.icon:null,me=e=>e.icon!==null&&!/^https?:\/\//i.test(e.icon)?e.icon:(e.name.charAt(0)||`?`).toUpperCase(),he=e=>{ue.value=new Set(ue.value).add(e.package)},V=e=>e>=1e3?`${(e/1e3).toFixed(e>=1e4?0:1)}k`:String(e),H=async()=>{try{let e=await ie.plugins();l.value=!0,_.value=e.enabled,C.value=e.autoUpdate,v.value=e.running,x.value=e.port}catch(e){if(typeof e?.message==`string`&&e.message.includes(`未由 ezllm 主进程托管`)){l.value=!1,te.value=e.message,_.value=!1,C.value=!1,v.value=!1,x.value=null;return}throw e}},U=async()=>{if(!B.value){M.value=[];return}let e=x.value;if(e!==null)try{let t=await E(T(e,`/packages`));M.value=Array.isArray(t.packages)?t.packages:[]}catch{M.value=[]}},ge=e=>{let t=Math.floor((Date.now()-e)/6e4);if(t<1)return`刚刚`;if(t<60)return`${String(t)} 分钟前`;let n=Math.floor(t/60);return n<24?`${String(n)} 小时前`:new Date(e).toLocaleDateString()},W=i(()=>{if(A.value)return`正在加载 ${String(se.value.loaded)}/${String(se.value.total)}…`;let e=j.value===null?``:ge(j.value.at),t=e===``?``:` · ${e}更新`,n=ce.value?` · 更新中…`:``;return`${String(k.value.length)} 个插件 · 已装 ${String(M.value.length)} 个${t}${n}`}),G=async(e=!1)=>{await le({force:e})},K=async()=>{try{await H()}catch(e){oe.value=e?.message??`插件服务状态加载失败`;return}await U(),await G()},q=async e=>{S.value=!0;try{let t=await ie.setPluginEnabled(e);_.value=t.enabled,v.value=t.running,x.value=t.port,c(e?`插件服务已开启`:`插件服务已关闭`,`success`),await U()}catch(e){await H().catch(()=>void 0),c(e?.message??`操作失败`,`error`)}finally{S.value=!1}},_e=async e=>{if(e){await q(!0);return}try{await b.confirm(`关闭插件服务?已装插件保留,但插件模型的请求将不可用。`,`关闭确认`,{confirmButtonText:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{await H().catch(()=>void 0);return}await q(!1)},Qe=async e=>{let t=!!e;w.value=!0;try{let e=await ie.setPluginAutoUpdate(t);C.value=e.autoUpdate,c(t?`已开启插件自动更新`:`已关闭插件自动更新`,`success`)}catch(e){await H().catch(()=>void 0),c(e?.message??`操作失败`,`error`)}finally{w.value=!1}},$e=async e=>{await tt(e.package)},et=async()=>{let e=F.value.trim();if(e!==``){de.value=!0;try{await tt(e),P.value=!1,F.value=``}finally{de.value=!1}}},tt=async e=>{let t=x.value;if(t===null){c(`插件服务未开启`,`error`);return}N.value=e;try{(await D(T(t,`/packages`),{package:e})).loaded===!1?c(`${e} 已安装但未加载成功(重启插件服务或查看日志)`,`warning`):c(`已安装 ${e}`,`success`),await U()}catch(e){c(e?.message??`安装失败`,`error`)}finally{N.value=null}},nt=async e=>{let t=x.value;if(t!==null){try{await b.confirm(`确定卸载 ${e}?该插件提供的模型将不可用。`,`确认卸载`,{confirmButtonText:`卸载`,cancelButtonText:`取消`,type:`warning`})}catch{return}N.value=e;try{await O(T(t,`/packages/${encodeURIComponent(e)}`)),c(`已卸载 ${e}`,`success`),await U()}catch(e){c(e?.message??`卸载失败`,`error`)}finally{N.value=null}}},rt=()=>{F.value=``,P.value=!0},it=async()=>{await U(),I.value=!0},at=i(()=>B.value?z.value?`检查已装插件是否有新版本`:`宿主当前无法检查更新`:`插件服务未开启`),ot=e=>{let t=L.value[e];return!t||!t.updateAvailable||!t.latest?null:`${t.current} → ${t.latest}`},st=async(e=!1)=>{let t=x.value;if(t===null){e||c(`插件服务未开启`,`error`);return}R.value=!0;try{let n=await E(T(t,`/packages/updates`)),r=Array.isArray(n.packages)?n.packages:[];z.value=n.canCheck;let i={};for(let e of r)i[e.package]=e;if(L.value=i,e)return;if(!n.canCheck){c(`宿主当前无法检查更新`,`warning`);return}let a=r.filter(e=>e.updateAvailable).length;c(a>0?`发现 ${String(a)} 个插件有新版本`:`全部插件已是最新`,`success`)}catch(t){e||c(t?.message??`检查更新失败`,`error`)}finally{R.value=!1}},ct=async e=>{let t=x.value,n=L.value[e]?.latest;if(t===null){c(`插件服务未开启`,`error`);return}if(n!=null){N.value=e;try{await D(T(t,`/packages`),{package:e,version:n});let r=await ie.restartPlugins();v.value=r.running,x.value=r.port,c(`已更新到 ${n} 并重启插件服务`,`success`),delete L.value[e],await U(),await st(!0)}catch(e){c(e?.message??`更新失败`,`error`)}finally{N.value=null}}},lt=s(null),ut=s(!1),dt=s(``),ft=s([]),pt=s(!1),mt=s(``),ht=s(``),gt=s(``),J=s(null),Y=s(!1),_t=s(``),vt=s(``),yt=s(``),bt=s(``),xt=s(void 0),St=s({}),X=s(null),Ct=s(!1),Z=s(!1),wt=s(``),Tt=s([]),Q=s({}),Et=s(void 0),$=s(null),Dt=s(!1),Ot=(e,t)=>{ht.value=e,mt.value=t.url??``,gt.value=t.instructions??``,J.value=null,pt.value=!0},kt=async e=>{let t=x.value;if(t===null)return;let n=Date.now()+18e4;for(;;){await new Promise(e=>setTimeout(e,2e3));let r;try{r=await E(T(t,`/login/${encodeURIComponent(e)}`))}catch(e){J.value=e?.message??`查询登录状态失败`;return}if(r.state===`success`){pt.value=!1,c(`已登录${r.accountId?`(${r.accountId})`:``}`,`success`),await U();return}if(r.state===`failed`){J.value=r.error??`登录失败`;return}if(Date.now()>n){J.value=`等待超时,可关闭后重新点击「登录」`;return}}},At=async(e,t,n,r)=>{let i=x.value;if(i===null){c(`插件服务未开启`,`error`);return}let a={};t!==void 0&&(a.method=t),Object.keys(n).length>0&&(a.inputs=n),r!==void 0&&r!==``&&(a.key=r);let o=await D(T(i,`/login/${encodeURIComponent(e)}`),a);if(o.needMethod===!0){dt.value=e,ft.value=o.methods,ut.value=!0;return}if(o.needInputs!==void 0&&o.needInputs.length>0){Y.value=!1,wt.value=e,Et.value=t,Tt.value=o.needInputs;let r={...o.inputs??n};for(let e of o.needInputs)r[e.key]=r[e.key]??``;Q.value=r,$.value=null,Z.value=!0;return}if(o.needKey===!0){Z.value=!1,_t.value=e,xt.value=t,vt.value=o.label??``,yt.value=o.placeholder??``,St.value={...o.inputs??n},bt.value=``,X.value=null,Y.value=!0;return}if(o.state===`success`){Z.value=!1,Y.value=!1,c(`已登录${o.accountId?`(${o.accountId})`:``}`,`success`),await U();return}if(o.state===`failed`){let e=o.error??`登录失败`;if(Y.value){X.value=e;return}if(Z.value){$.value=e;return}c(e,`error`);return}Z.value=!1,Y.value=!1,Ot(e,o),kt(e)},jt=async(e,t)=>{lt.value=e;try{await At(e,t,{})}catch(e){c(e?.message??`发起登录失败`,`error`)}finally{lt.value=null}},Mt=async e=>{ut.value=!1,await jt(dt.value,e)},Nt=async()=>{Dt.value=!0;try{await At(wt.value,Et.value,{...Q.value})}catch(e){$.value=e?.message??`提交失败`}finally{Dt.value=!1}},Pt=async()=>{if(bt.value.trim()===``){X.value=`请填写密钥`;return}Ct.value=!0,X.value=null;try{await At(_t.value,xt.value,{...St.value},bt.value)}catch(e){X.value=e?.message??`提交失败`}finally{Ct.value=!1}};return ee(K),(n,i)=>{let s=f(`el-switch`),c=f(`el-button`),ee=f(`el-icon`),b=f(`el-alert`),x=f(`el-tag`),ie=f(`el-card`),ae=f(`el-input`),T=f(`el-form-item`),E=f(`el-form`),D=f(`el-dialog`),O=f(`el-table-column`),se=f(`el-table`),j=f(`el-option`),ce=f(`el-select`);return u(),r(`div`,null,[m(`div`,ye,[i[22]||=m(`div`,null,[m(`div`,{class:`page-head-title`},`插件`),m(`div`,{class:`page-head-sub`},` 订阅社区 OpenCode 插件——把订阅账号(CodeBuddy、智谱 Coding Plan 等)当作供应商接入网关 `)],-1),m(`div`,be,[t(s,{modelValue:_.value,"onUpdate:modelValue":i[0]||=e=>_.value=e,loading:S.value,disabled:!l.value||S.value,"active-text":`插件服务`,"inline-prompt":``,onChange:_e},null,8,[`modelValue`,`loading`,`disabled`]),t(s,{modelValue:C.value,"onUpdate:modelValue":i[1]||=e=>C.value=e,loading:w.value,disabled:!l.value||w.value,"active-text":`自动更新`,"inline-prompt":``,title:`插件会在后台每小时检查并更新`,onChange:Qe},null,8,[`modelValue`,`loading`,`disabled`]),t(c,{disabled:!v.value,onClick:it},{default:h(()=>[...i[19]||=[a(`已装插件`,-1)]]),_:1},8,[`disabled`]),t(c,{disabled:!v.value,onClick:rt},{default:h(()=>[t(ee,null,{default:h(()=>[t(o(re))]),_:1}),i[20]||=a(` 手动安装 `,-1)]),_:1},8,[`disabled`]),t(c,{loading:o(A),onClick:i[2]||=e=>G(!0)},{default:h(()=>[...i[21]||=[a(`刷新`,-1)]]),_:1},8,[`loading`])])]),l.value?v.value?p(``,!0):(u(),e(b,{key:1,type:`info`,"show-icon":``,closable:!1,class:`mb-16`,title:`插件服务未开启`},{default:h(()=>[i[24]||=m(`div`,{class:`muted-sm`},`开启后即可安装并加载插件;下方清单仍可浏览。`,-1),t(c,{size:`small`,type:`primary`,class:`mt-8`,loading:S.value,onClick:i[3]||=e=>q(!0)},{default:h(()=>[...i[23]||=[a(` 开启插件服务 `,-1)]]),_:1},8,[`loading`])]),_:1})):(u(),e(b,{key:0,type:`warning`,"show-icon":``,closable:!1,class:`mb-16`,title:`插件服务不可用`},{default:h(()=>[a(d(te.value),1)]),_:1})),o(oe)?(u(),e(b,{key:2,type:`error`,"show-icon":``,closable:!1,class:`mb-16`,title:o(oe)},{default:h(()=>[t(c,{size:`small`,onClick:G},{default:h(()=>[...i[25]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):p(``,!0),t(ie,{shadow:`never`},{header:h(()=>[m(`div`,xe,[i[26]||=m(`span`,{class:`fw-600`},`社区插件`,-1),m(`span`,Se,d(W.value),1)])]),default:h(()=>[o(A)&&o(k).length===0?(u(),r(`div`,Ce,`正在从社区清单加载…`)):o(k).length===0?(u(),r(`div`,we,` 清单里没有本宿主支持的插件(只收 provider 类),可点右上角「刷新」重试,或用「手动安装」直接按包名安装。 `)):(u(),r(`div`,Te,[(u(!0),r(y,null,g(o(k),t=>(u(),r(`div`,{key:t.package,class:`plugin-card`},[m(`div`,Ee,[m(`div`,De,[pe(t)?(u(),r(`img`,{key:0,src:pe(t),alt:t.name,onError:e=>he(t)},null,40,Oe)):(u(),r(`span`,ke,d(me(t)),1))]),m(`div`,Ae,[m(`div`,{class:`plugin-name`,title:t.name},d(t.name),9,je),m(`div`,Me,[t.community?(u(),e(x,{key:0,size:`small`,type:`info`,"disable-transitions":``},{default:h(()=>[a(d(t.community),1)]),_:2},1024)):p(``,!0)])]),m(`div`,Ne,[fe(t)?(u(),e(x,{key:0,type:`success`,size:`small`,"disable-transitions":``},{default:h(()=>[...i[27]||=[a(`已装`,-1)]]),_:1})):(u(),e(c,{key:1,type:`primary`,size:`small`,disabled:!B.value||N.value===t.package,loading:N.value===t.package,onClick:e=>$e(t)},{default:h(()=>[...i[28]||=[a(` 安装 `,-1)]]),_:1},8,[`disabled`,`loading`,`onClick`]))])]),m(`div`,{class:`plugin-summary`,title:t.summary??``},d(t.summary??`(清单未提供简介)`),9,Pe),m(`div`,Fe,[m(`span`,null,`供应商 `+d(t.providers.length),1),t.weeklyDownloads===null?p(``,!0):(u(),r(`span`,Ie,d(V(t.weeklyDownloads))+`/周`,1)),t.version?(u(),r(`span`,Le,`v`+d(t.version),1)):(u(),r(`span`,Re,`版本未知`))])]))),128))]))]),_:1}),t(D,{modelValue:P.value,"onUpdate:modelValue":i[6]||=e=>P.value=e,title:`手动安装插件`,width:`520px`},{footer:h(()=>[t(c,{onClick:i[5]||=e=>P.value=!1},{default:h(()=>[...i[30]||=[a(`取消`,-1)]]),_:1}),t(c,{type:`primary`,loading:de.value,disabled:F.value.trim()===``,onClick:et},{default:h(()=>[...i[31]||=[a(` 安装 `,-1)]]),_:1},8,[`loading`,`disabled`])]),default:h(()=>[t(E,{"label-position":`top`},{default:h(()=>[t(T,{label:`npm 包名`},{default:h(()=>[t(ae,{modelValue:F.value,"onUpdate:modelValue":i[4]||=e=>F.value=e,placeholder:`例:@magpie-community/opencode-workbuddy-auth`,clearable:``},null,8,[`modelValue`]),i[29]||=m(`div`,{class:`muted-sm`},[a(`可带版本(`),m(`span`,{class:`mono`},`name@1.2.3`),a(`);清单加载不出来时用这个。`)],-1)]),_:1})]),_:1})]),_:1},8,[`modelValue`]),t(D,{modelValue:I.value,"onUpdate:modelValue":i[9]||=e=>I.value=e,title:`已装插件`,width:`880px`},{footer:h(()=>[t(c,{disabled:!B.value||!z.value||N.value!==null,loading:R.value,title:at.value,onClick:i[7]||=e=>st()},{default:h(()=>[...i[39]||=[a(`检查更新`,-1)]]),_:1},8,[`disabled`,`loading`,`title`]),t(c,{onClick:i[8]||=e=>I.value=!1},{default:h(()=>[...i[40]||=[a(`关闭`,-1)]]),_:1})]),default:h(()=>[t(se,{data:M.value,"empty-text":`尚未安装任何插件`},{default:h(()=>[t(O,{label:`包名`,"min-width":`190`},{default:h(({row:e})=>[m(`div`,ze,d(e.package),1)]),_:1}),t(O,{label:`供应商`,"min-width":`200`},{default:h(({row:n})=>[n.providers.length?p(``,!0):(u(),r(`div`,Be,`-`)),(u(!0),r(y,null,g(n.providers,n=>(u(),r(`div`,{key:n.id,class:`provider-line`},[m(`span`,Ve,d(n.id),1),n.signedIn?(u(),e(x,{key:0,type:`success`,size:`small`,"disable-transitions":``},{default:h(()=>[...i[32]||=[a(`已登录`,-1)]]),_:1})):(u(),r(y,{key:1},[i[34]||=m(`span`,{class:`muted-sm`},`未登录`,-1),t(c,{link:``,type:`primary`,size:`small`,loading:lt.value===n.id,onClick:e=>jt(n.id)},{default:h(()=>[...i[33]||=[a(` 登录 `,-1)]]),_:1},8,[`loading`,`onClick`])],64))]))),128))]),_:1}),t(O,{label:`版本`,width:`110`},{default:h(({row:e})=>[m(`span`,He,d(e.version||`-`),1)]),_:1}),t(O,{label:`更新`,width:`150`},{default:h(({row:e})=>[ot(e.package)?(u(),r(y,{key:0},[m(`div`,Ue,d(ot(e.package)),1),t(c,{link:``,type:`primary`,size:`small`,disabled:N.value!==null||R.value,loading:N.value===e.package,onClick:t=>ct(e.package)},{default:h(()=>[...i[35]||=[a(`更新`,-1)]]),_:1},8,[`disabled`,`loading`,`onClick`])],64)):p(``,!0)]),_:1}),t(O,{label:`状态`,width:`90`,align:`center`},{default:h(({row:t})=>[t.loaded?(u(),e(x,{key:0,type:`success`,size:`small`,"disable-transitions":``},{default:h(()=>[...i[36]||=[a(`已加载`,-1)]]),_:1})):(u(),e(x,{key:1,type:`danger`,size:`small`,"disable-transitions":``},{default:h(()=>[...i[37]||=[a(`加载失败`,-1)]]),_:1}))]),_:1}),t(O,{label:`操作`,width:`90`,align:`center`},{default:h(({row:e})=>[t(c,{link:``,type:`danger`,loading:N.value===e.package,onClick:t=>nt(e.package)},{default:h(()=>[...i[38]||=[a(`卸载`,-1)]]),_:1},8,[`loading`,`onClick`])]),_:1})]),_:1},8,[`data`])]),_:1},8,[`modelValue`]),t(D,{modelValue:ut.value,"onUpdate:modelValue":i[11]||=e=>ut.value=e,title:`选择登录方式`,width:`460px`},{footer:h(()=>[t(c,{onClick:i[10]||=e=>ut.value=!1},{default:h(()=>[...i[41]||=[a(`取消`,-1)]]),_:1})]),default:h(()=>[i[42]||=m(`div`,{class:`muted-sm`},`该插件提供多种登录方式,选一种:`,-1),m(`div`,We,[(u(!0),r(y,null,g(ft.value,t=>(u(),e(c,{key:t.label,class:`method-btn`,onClick:e=>Mt(t.label)},{default:h(()=>[a(d(t.label||t.type),1)]),_:2},1032,[`onClick`]))),128))])]),_:1},8,[`modelValue`]),t(D,{modelValue:Z.value,"onUpdate:modelValue":i[13]||=e=>Z.value=e,title:`登录 ${wt.value}`,width:`480px`},{footer:h(()=>[t(c,{onClick:i[12]||=e=>Z.value=!1},{default:h(()=>[...i[43]||=[a(`取消`,-1)]]),_:1}),t(c,{type:`primary`,loading:Dt.value,onClick:Nt},{default:h(()=>[...i[44]||=[a(`确定`,-1)]]),_:1},8,[`loading`])]),default:h(()=>[(u(!0),r(y,null,g(Tt.value,t=>(u(),r(`div`,{key:t.key,class:`field-row`},[m(`div`,Ge,d(t.message||t.key),1),t.type===`select`?(u(),e(ce,{key:0,modelValue:Q.value[t.key],"onUpdate:modelValue":e=>Q.value[t.key]=e,class:`mt-8`,placeholder:`请选择`,style:{width:`100%`}},{default:h(()=>[(u(!0),r(y,null,g(t.options,t=>(u(),e(j,{key:t.value,label:t.label??t.value,value:t.value??``},{default:h(()=>[m(`span`,null,d(t.label??t.value),1),t.hint?(u(),r(`span`,Ke,`(`+d(t.hint)+`)`,1)):p(``,!0)]),_:2},1032,[`label`,`value`]))),128))]),_:2},1032,[`modelValue`,`onUpdate:modelValue`])):(u(),e(ae,{key:1,modelValue:Q.value[t.key],"onUpdate:modelValue":e=>Q.value[t.key]=e,class:`mt-8`,placeholder:t.placeholder||``,onKeyup:ne(Nt,[`enter`])},null,8,[`modelValue`,`onUpdate:modelValue`,`placeholder`]))]))),128)),$.value?(u(),e(b,{key:0,type:`error`,"show-icon":``,closable:!1,class:`mt-8`,title:$.value},null,8,[`title`])):p(``,!0)]),_:1},8,[`modelValue`,`title`]),t(D,{modelValue:Y.value,"onUpdate:modelValue":i[16]||=e=>Y.value=e,title:`登录 ${_t.value}`,width:`480px`},{footer:h(()=>[t(c,{onClick:i[15]||=e=>Y.value=!1},{default:h(()=>[...i[45]||=[a(`取消`,-1)]]),_:1}),t(c,{type:`primary`,loading:Ct.value,onClick:Pt},{default:h(()=>[...i[46]||=[a(`确定`,-1)]]),_:1},8,[`loading`])]),default:h(()=>[m(`div`,qe,d(vt.value||`该登录方式需要一枚密钥`),1),t(ae,{modelValue:bt.value,"onUpdate:modelValue":i[14]||=e=>bt.value=e,class:`mt-8`,placeholder:yt.value||`粘贴密钥`,"show-password":``,onKeyup:ne(Pt,[`enter`])},null,8,[`modelValue`,`placeholder`]),X.value?(u(),e(b,{key:0,type:`error`,"show-icon":``,closable:!1,class:`mt-8`,title:X.value},null,8,[`title`])):p(``,!0)]),_:1},8,[`modelValue`,`title`]),t(D,{modelValue:pt.value,"onUpdate:modelValue":i[18]||=e=>pt.value=e,title:`登录 ${ht.value}`,width:`480px`},{footer:h(()=>[t(c,{onClick:i[17]||=e=>pt.value=!1},{default:h(()=>[...i[48]||=[a(`关闭`,-1)]]),_:1})]),default:h(()=>[m(`div`,Je,d(gt.value||`正在读取本机已登录的凭据…`),1),mt.value?(u(),r(`div`,Ye,[m(`a`,{class:`el-button el-button--primary`,href:mt.value,target:`_blank`,rel:`noopener`},` 打开登录页 `,8,Xe),i[47]||=m(`div`,{class:`muted-sm mt-8`},`在打开的页面完成登录即可,本页会自动检测(最长等待几分钟)。`,-1)])):p(``,!0),J.value?(u(),e(b,{key:1,type:`error`,"show-icon":``,closable:!1,class:`mt-8`,title:J.value},null,8,[`title`])):(u(),r(`div`,Ze,`等待登录完成…`))]),_:1},8,[`modelValue`,`title`])])}}}),[[`__scopeId`,`data-v-45469a71`]]);export{Qe as default};
@@ -0,0 +1 @@
1
+ .plugin-grid[data-v-45469a71]{grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:16px;display:grid}.plugin-card[data-v-45469a71]{border:1px solid var(--el-border-color-light);border-radius:8px;flex-direction:column;gap:10px;padding:16px;transition:border-color .15s;display:flex}.plugin-card[data-v-45469a71]:hover{border-color:var(--el-color-primary-light-5)}.card-top[data-v-45469a71]{align-items:flex-start;gap:12px;display:flex}.plugin-icon[data-v-45469a71]{background:var(--el-fill-color-light);border-radius:8px;flex-shrink:0;justify-content:center;align-items:center;width:40px;height:40px;font-size:18px;font-weight:600;display:flex;overflow:hidden}.plugin-icon img[data-v-45469a71]{object-fit:contain;width:100%;height:100%}.plugin-titles[data-v-45469a71]{flex:1;min-width:0}.plugin-name[data-v-45469a71]{text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:600;overflow:hidden}.plugin-tags[data-v-45469a71]{flex-wrap:wrap;gap:6px;margin-top:4px;display:flex}.plugin-action[data-v-45469a71]{flex-shrink:0}.plugin-summary[data-v-45469a71]{color:var(--el-text-color-regular);-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;min-height:39px;font-size:13px;line-height:1.5;display:-webkit-box;overflow:hidden}.plugin-meta[data-v-45469a71]{color:var(--el-text-color-secondary);border-top:1px solid var(--el-border-color-lighter);flex-wrap:wrap;gap:12px;padding-top:10px;font-size:12px;display:flex}.mono[data-v-45469a71]{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.provider-line[data-v-45469a71]{align-items:center;gap:8px;display:flex}.provider-line[data-v-45469a71]:not(:last-child){margin-bottom:4px}.method-list[data-v-45469a71]{flex-direction:column;gap:8px;margin-top:12px;display:flex}.method-btn[data-v-45469a71]{justify-content:flex-start;margin-left:0}.field-row[data-v-45469a71]:not(:first-child){margin-top:12px}