ezllm 0.0.29 → 0.0.30

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 (48) hide show
  1. package/dist/cli.js +30 -28
  2. package/dist/daemon.js +18 -18
  3. package/dist/server.js +69 -75
  4. package/dist/web-ui/assets/DashboardView-DOwvAtq-.js +1 -0
  5. package/dist/web-ui/assets/LayoutView-B4fUaz9C.js +1 -0
  6. package/dist/web-ui/assets/LayoutView-Cx9vUqeZ.css +1 -0
  7. package/dist/web-ui/assets/LoginView-BQEkBw8e.css +1 -0
  8. package/dist/web-ui/assets/LoginView-G89QGoG0.js +1 -0
  9. package/dist/web-ui/assets/LogsView--ahw0k4u.js +9 -0
  10. package/dist/web-ui/assets/{LogsView-BZCLikyn.css → LogsView-C5nwx_hg.css} +1 -1
  11. package/dist/web-ui/assets/ProvidersView-Bfb6bLjb.js +14 -0
  12. package/dist/web-ui/assets/ProvidersView-CLtKgvo_.css +1 -0
  13. package/dist/web-ui/assets/ServiceStatusView-Bkg3N6YJ.css +1 -0
  14. package/dist/web-ui/assets/ServiceStatusView-DAFz0O6i.js +2 -0
  15. package/dist/web-ui/assets/SettingsView-DNTvqQlE.js +1 -0
  16. package/dist/web-ui/assets/SetupView-BA06j75c.js +1 -0
  17. package/dist/web-ui/assets/SetupView-BDyHouba.css +1 -0
  18. package/dist/web-ui/assets/config-B6AvsVNP.js +1 -0
  19. package/dist/web-ui/assets/index-kwJNWvLc.js +49 -0
  20. package/dist/web-ui/assets/{index-DmoPyGio.css → index-wQvjidwN.css} +1 -1
  21. package/dist/web-ui/assets/message-CYCqk4yf.js +2 -0
  22. package/dist/web-ui/assets/providers-C9CHuG_i.js +1 -0
  23. package/dist/web-ui/assets/router-Oh7GPjpX.js +6 -0
  24. package/dist/web-ui/assets/{useCopyToast-SPDhUFJc.js → useCopyToast-5I0bBbzu.js} +1 -1
  25. package/dist/web-ui/assets/{useManagerApi-B65ileRW.js → useManagerApi-LTdyIrJc.js} +1 -1
  26. package/dist/web-ui/assets/useToast-C4nXu2HZ.js +1 -0
  27. package/dist/web-ui/index.html +4 -4
  28. package/package.json +6 -3
  29. package/dist/web-ui/assets/DashboardView-5ujMkgws.js +0 -1
  30. package/dist/web-ui/assets/DashboardView-CZy4j9_m.css +0 -1
  31. package/dist/web-ui/assets/LayoutView-C-x9LlJB.js +0 -1
  32. package/dist/web-ui/assets/LayoutView-DMNmIelM.css +0 -1
  33. package/dist/web-ui/assets/LoginView-BZnxf_XD.css +0 -1
  34. package/dist/web-ui/assets/LoginView-Dgr8SbIP.js +0 -1
  35. package/dist/web-ui/assets/LogsView-DME2_Vhc.js +0 -9
  36. package/dist/web-ui/assets/ProvidersView-B__welRn.css +0 -1
  37. package/dist/web-ui/assets/ProvidersView-CcTikZnF.js +0 -14
  38. package/dist/web-ui/assets/ServiceStatusView-C4N2XQ_w.js +0 -2
  39. package/dist/web-ui/assets/ServiceStatusView-CwXVx_18.css +0 -1
  40. package/dist/web-ui/assets/SettingsView-Cck08cQ7.js +0 -1
  41. package/dist/web-ui/assets/SetupView-B3SahEFi.css +0 -1
  42. package/dist/web-ui/assets/SetupView-DbiSodBy.js +0 -1
  43. package/dist/web-ui/assets/config-DcxW5IHq.js +0 -1
  44. package/dist/web-ui/assets/index-Bxg3HL8C.js +0 -49
  45. package/dist/web-ui/assets/message-BfNKbnQ4.js +0 -2
  46. package/dist/web-ui/assets/providers-DBzc7lYt.js +0 -1
  47. package/dist/web-ui/assets/router-BbFt1lFf.js +0 -6
  48. package/dist/web-ui/assets/useToast-D0wtmNdH.js +0 -1
@@ -0,0 +1 @@
1
+ .quota-block[data-v-9b7e8a70]{background:#fafbfc;border:1px solid #f0f2f5;border-radius:6px;margin-bottom:4px;padding:8px 10px}.quota-header[data-v-9b7e8a70]{justify-content:space-between;align-items:center;gap:8px;margin-bottom:6px;display:flex}.quota-block-title[data-v-9b7e8a70]{color:#303133;flex-shrink:0;font-size:13px;font-weight:600}.quota-header-stats[data-v-9b7e8a70]{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:4px;min-width:0;display:flex}.quota-hint[data-v-9b7e8a70]{color:#c0c4cc;font-size:12px}.quota-error[data-v-9b7e8a70]{color:#f56c6c;word-break:break-all;margin-bottom:4px;font-size:12px}.quota-row[data-v-9b7e8a70]{align-items:flex-start;gap:8px;padding:3px 0;display:flex}.quota-label[data-v-9b7e8a70]{color:#909399;flex-shrink:0;width:72px;font-size:12px;line-height:18px}.quota-main[data-v-9b7e8a70]{flex:1;min-width:0}.quota-main[data-v-9b7e8a70] .el-progress{width:100%}.quota-main[data-v-9b7e8a70] .el-progress-bar__outer{background-color:#f2f2f2}.quota-main[data-v-9b7e8a70] .el-progress-bar__inner{align-items:center;display:flex}.quota-main[data-v-9b7e8a70] .el-progress-bar__innerText{color:#303133;white-space:nowrap;margin:0 5px;font-size:12px;line-height:1}.quota-cap-null[data-v-9b7e8a70]{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-90cee0de]{min-height:70vh;overflow-y:auto}.muted-sm[data-v-90cee0de]{color:#909399;font-size:12px;line-height:1.6}.status-row[data-v-90cee0de]{margin-top:4px}.test-ok-text-full[data-v-90cee0de]{color:#16a34a;font-size:12px}.test-fail-text-full[data-v-90cee0de]{color:#dc2626;word-break:break-all;font-size:12px}.col-help-icon[data-v-90cee0de]{margin-left:4px}.ghost[data-v-959fb962]{opacity:.4}.provider-grid[data-v-959fb962]{grid-template-columns:repeat(2,1fr);gap:16px;display:grid}@media (width<=992px){.provider-grid[data-v-959fb962]{grid-template-columns:1fr}}
@@ -0,0 +1 @@
1
+ .service-status-page[data-v-30961cfb]{flex-direction:column;height:calc(100vh - 124px);display:flex;overflow:hidden}.main-card[data-v-30961cfb]{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.main-card[data-v-30961cfb] .el-card__body{flex-direction:column;height:100%;display:flex;overflow:hidden}.legend[data-v-30961cfb]{color:#606266;flex-shrink:0;align-items:center;gap:6px;margin-bottom:8px;font-size:12px;display:flex}.legend-gradient[data-v-30961cfb]{background:linear-gradient(90deg,#67c23a,#e6a23c,#f56c6c);border-radius:2px;width:96px;height:10px}.legend-swatch[data-v-30961cfb]{border-radius:2px;width:14px;height:10px;margin-left:10px}.legend-swatch--down[data-v-30961cfb]{background-color:#909399}.legend-swatch--empty[data-v-30961cfb]{background-color:#f2f3f5;border:1px solid #ebeef5}.hint[data-v-30961cfb]{flex-shrink:0;margin-bottom:12px}.gantt-wrap[data-v-30961cfb]{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.gantt[data-v-30961cfb]{flex:1;min-height:0;overflow:hidden auto}.gantt-row[data-v-30961cfb]{border-bottom:1px solid #f2f6fc;align-items:center;height:32px;display:flex}.gantt-row[data-v-30961cfb]:hover{background-color:#fafcff}.gantt-head[data-v-30961cfb]{z-index:1;color:#909399;background-color:#fff;border-bottom:1px solid #ebeef5;height:auto;min-height:34px;padding:2px 0;font-size:12px;font-weight:600;position:sticky;top:0}.col-name[data-v-30961cfb]{flex:0 0 240px;width:240px;padding-right:12px;font-size:13px}.col-status[data-v-30961cfb]{color:#606266;flex:0 0 100px;width:100px;padding-right:12px;font-size:13px}.col-cells[data-v-30961cfb]{flex:1;min-width:0;display:flex}.cell[data-v-30961cfb]{flex:1 1 0;min-width:0;height:20px;box-shadow:inset -1px 0 #fff}.cell[data-v-30961cfb]:last-child{box-shadow:none}.cell--head[data-v-30961cfb]{white-space:nowrap;flex-direction:column;align-items:center;height:auto;font-size:10px;font-weight:400;line-height:1.15;display:flex;overflow:hidden}.cell-head-date[data-v-30961cfb]{color:#c0c4cc;font-size:9px}.cell--empty[data-v-30961cfb]{background-color:#f2f3f5}.gantt-empty[data-v-30961cfb]{color:#909399;flex:1;justify-content:center;align-items:center;font-size:13px;display:flex}.model-name[data-v-30961cfb]{white-space:nowrap;text-overflow:ellipsis;display:block;overflow:hidden}
@@ -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,Q as s,Tt as c,V as l,Wt as u,Z as d,a as f,at as p,et as m,fn as h,ht as g,it as _,j as v,k as y,ln as ee,mt as b,nt as x,sn as S,vt as C,w}from"./router-Oh7GPjpX.js";import{t as T}from"./index-kwJNWvLc.js";import{n as E,t as D}from"./useCopyToast-5I0bBbzu.js";import{t as O}from"./useToast-C4nXu2HZ.js";import{c as te,i as k}from"./format-OBe8peUU.js";l(),C(),u();var ne={class:`service-status-page`},re={class:`flex-between`},ie={class:`flex-gap-8`},ae={class:`flex-gap-8`},oe={class:`gantt-wrap`},se={key:0,class:`gantt`},ce={class:`gantt-row gantt-head`},le={class:`col-cells`},ue=[`title`],de={class:`cell-head-date`},fe={class:`col-name`},pe=[`title`,`onClick`],me=[`title`],he={class:`col-cells`},A=[`title`],j={key:1,class:`gantt-empty`},M=36e5,N=24,P=`#909399`,F=T(n({__name:`ServiceStatusView`,setup(n){let{toast:l}=O(),{copyWithToast:u}=D(),{loadError:C,run:T}=E(`延迟数据加载失败,请重试`),F=c([]),I=c(!0),L=c(!1),R=c(null),z=c(!1),B=c(!1),V,H,U=c(G()),W=c(new Map);function G(){let e=new Date,t=new Date(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours()).getTime();return Array.from({length:N},(e,n)=>t-(23-n)*M)}let K=e=>{let t=new Date(e);if(Number.isNaN(t.getTime()))return`-`;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:00`},ge=i(()=>U.value.map(e=>{let t=new Date(e),n=e=>String(e).padStart(2,`0`),r=n(t.getHours());return{start:e,dateLabel:`${n(t.getMonth()+1)}-${n(t.getDate())}`,hourLabel:r,fullLabel:`${K(e)} - ${r}:59`}})),_e=[103,194,58],q=[230,162,60],ve=[245,108,108],J=i(()=>{let e=[];for(let t of W.value.values())for(let n of t.values())n.avgLatencyMs!==null&&e.push(n.avgLatencyMs);if(e.length===0)return{min:0,max:0};let t=e[0],n=e[0];for(let r of e)r<t&&(t=r),r>n&&(n=r);return{min:t,max:n}}),ye=e=>{let{min:t,max:n}=J.value,r=n===t?0:(e-t)/(n-t),[i,a]=r<=.5?[_e,q]:[q,ve],o=r<=.5?r*2:(r-.5)*2,s=i.map((e,t)=>Math.round(e+(a[t]-e)*o));return`rgba(${String(s[0])}, ${String(s[1])}, ${String(s[2])}, 0.9)`},Y=(e,t)=>{let n=`${K(t)} - ${String(new Date(t+M).getHours()).padStart(2,`0`)}:00`;return e===void 0||e.total===0?`${n}\n无探测数据`:`${n}\n平均延迟 ${k(e.avgLatencyMs)}\n成功 ${String(e.success)} / 失败 ${String(e.failed)}`},X=i(()=>xe.value.map(e=>{let t=W.value.get(e.model),n=U.value.map(e=>{let n=t?.get(e);return n!==void 0&&n.failed>0?{start:e,className:`cell--down`,style:{backgroundColor:P},title:Y(n,e)}:n===void 0||n.avgLatencyMs===null?{start:e,className:`cell--empty`,style:{},title:Y(n,e)}:{start:e,className:``,style:{backgroundColor:ye(n.avgLatencyMs)},title:Y(n,e)}});return{model:e.model,avg24h:e.avg24h,statusTitle:[e.avg24h===null?`最近 24 小时无成功探测记录`:`最近 24 小时成功探测平均延迟 ${k(e.avg24h)}`,e.lastLatencyMs==null?`最近一次探测:无成功延迟记录`:`最近一次探测延迟 ${k(e.lastLatencyMs)}`].join(`
2
+ `),cells:n}})),be=(e,t)=>e===null&&t===null?0:e===null?1:t===null?-1:e-t,xe=i(()=>[...F.value].sort((e,t)=>{let n=e.lastOk===!1;if(n!==(t.lastOk===!1))return n?1:-1;let r=be(e.avg24h,t.avg24h);return r===0?e.model.localeCompare(t.model):r})),Z=async e=>{if(e.length===0){W.value=new Map;return}let t=await Promise.all(e.map(async e=>{try{let t=await f.get(`/api/latency/trend?model=${encodeURIComponent(e)}&granularity=hour`);return[e,new Map((t.buckets??[]).map(e=>[e.bucketStart,e]))]}catch{return[e,new Map]}}));W.value=new Map(t)},Q=async()=>{let e=await f.get(`/api/latency/history`);return F.value=e.models??[],L.value=e.running,R.value=e.lastRunAt,e},$=()=>T(async()=>{try{await Q(),U.value=G(),await Z(F.value.map(e=>e.model))}finally{I.value=!1}}),Se=()=>$(),Ce=()=>{B.value?V=window.setInterval(()=>void $(),5e3):V!==void 0&&(window.clearInterval(V),V=void 0)},we=async()=>{z.value=!0;try{await f.post(`/api/latency/run`)}catch(e){l(e.message,`error`),z.value=!1;return}H=window.setInterval(async()=>{try{(await Q()).running||(window.clearInterval(H),H=void 0,z.value=!1,U.value=G(),await Z(F.value.map(e=>e.model)))}catch{}},2e3)};return d(()=>{$()}),s(()=>{V!==void 0&&window.clearInterval(V),H!==void 0&&window.clearInterval(H)}),(n,i)=>{let s=_(`el-button`),c=_(`el-alert`),l=_(`el-tag`),d=_(`el-checkbox`),f=_(`el-empty`),T=_(`el-card`),E=p(`loading`);return m(),r(`div`,ne,[o(C)?(m(),e(c,{key:0,title:o(C),type:`error`,"show-icon":``,closable:!1,class:`mb-16`},{default:b(()=>[t(s,{size:`small`,onClick:Se},{default:b(()=>[...i[1]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):v(``,!0),t(T,{shadow:`never`,class:`main-card`},{header:b(()=>[y(`div`,re,[y(`div`,ie,[i[3]||=y(`span`,{class:`fw-600`},`服务状态`,-1),L.value?(m(),e(l,{key:0,type:`warning`,size:`small`},{default:b(()=>[...i[2]||=[a(`测试进行中`,-1)]]),_:1})):R.value?(m(),e(l,{key:1,type:`info`,size:`small`},{default:b(()=>[a(` 上次测试 `+h(o(te)(R.value)),1)]),_:1})):v(``,!0)]),y(`div`,ae,[t(d,{modelValue:B.value,"onUpdate:modelValue":i[0]||=e=>B.value=e,onChange:Ce},{default:b(()=>[...i[4]||=[a(` 自动刷新(5s) `,-1)]]),_:1},8,[`modelValue`]),t(s,{loading:z.value,onClick:we},{default:b(()=>[...i[5]||=[a(` 延迟测试 `,-1)]]),_:1},8,[`loading`])])])]),default:b(()=>[i[9]||=y(`div`,{class:`legend`},[y(`span`,{class:`legend-text`},`延迟`),y(`span`,{class:`legend-text`},`低`),y(`span`,{class:`legend-gradient`}),y(`span`,{class:`legend-text`},`高`),y(`span`,{class:`legend-swatch legend-swatch--down`}),y(`span`,{class:`legend-text`},`该小时有失败探测`),y(`span`,{class:`legend-swatch legend-swatch--empty`}),y(`span`,{class:`legend-text`},`无探测数据`)],-1),g((m(),r(`div`,oe,[i[8]||=y(`div`,{class:`muted-sm hint`},` 右侧 24 格为最近 24 小时(每格 1 小时,本地整点对齐,最右格为当前小时)。 格子底色为当小时成功探测的平均延迟,全表统一色标(本期最快→最慢 绿→红); 当小时存在失败探测即视为不可用,显示灰色。 行按 24h 平均延迟升序,最近一次探测失败的模型沉底。 `,-1),X.value.length>0?(m(),r(`div`,se,[y(`div`,ce,[i[6]||=y(`div`,{class:`col-name`},`模型名称`,-1),i[7]||=y(`div`,{class:`col-status`},`状态`,-1),y(`div`,le,[(m(!0),r(w,null,x(ge.value,e=>(m(),r(`div`,{key:e.start,class:`cell cell--head`,title:e.fullLabel},[y(`span`,de,h(e.dateLabel),1),y(`span`,null,h(e.hourLabel),1)],8,ue))),128))])]),(m(!0),r(w,null,x(X.value,e=>(m(),r(`div`,{key:e.model,class:`gantt-row`},[y(`div`,fe,[y(`span`,{class:`copy-text model-name`,title:e.model,onClick:t=>o(u)(e.model)},h(e.model),9,pe)]),y(`div`,{class:`col-status`,title:e.statusTitle},h(o(k)(e.avg24h)),9,me),y(`div`,he,[(m(!0),r(w,null,x(e.cells,e=>(m(),r(`div`,{key:e.start,class:S([`cell`,e.className]),style:ee(e.style),title:e.title},null,14,A))),128))])]))),128))])):(m(),r(`div`,j,[t(f,{description:`暂无延迟数据,点击「延迟测试」开始`,"image-size":80})]))])),[[E,I.value]])]),_:1})])}}}),[[`__scopeId`,`data-v-30961cfb`]]);export{F as default};
@@ -0,0 +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 p,et as m,fn as h,ht as g,it as _,j as v,k as y,mt as b,n as x,nt as S,vt as C,w}from"./router-Oh7GPjpX.js";import{n as T,t as E}from"./index-kwJNWvLc.js";import{n as D,t as O}from"./useManagerApi-LTdyIrJc.js";import{t as k}from"./config-B6AvsVNP.js";import{n as A,t as j}from"./useCopyToast-5I0bBbzu.js";import{t as M}from"./useToast-C4nXu2HZ.js";import{n as N,t as P}from"./version-DegxwpkG.js";l(),u(),C();var F={class:`flex-between`},I={class:`muted-sm mb-8`},L={class:`switch-row`},R={class:`switch-info`},z={class:`switch-title`},B={class:`switch-row`},V={class:`switch-info`},H={class:`switch-title`},U={class:`switch-row`},W={class:`switch-info`},G={class:`switch-title`},K=E(n({__name:`HarnessSwitches`,setup(n){let{toast:i}=M(),o=c(!0),s=c(!1),l=c(null),u=c(null),f=c(null),x=c(null),S=c(`success`),C=async e=>{e||(l.value?s.value=!0:o.value=!0);try{l.value=await O.harness(),u.value=null}catch(t){e||(u.value=t.message)}finally{e||(o.value=!1,s.value=!1)}};d(()=>C(!1));let E={claudeCode:{label:`Claude Code`,file:`~/.claude/settings.json`,toggle:O.setClaudeCode},codex:{label:`Codex CLI`,file:`~/.codex/config.toml`,toggle:O.setCodex},dsh:{label:`DeepSeek Harness`,file:`~/.dsh/settings.yaml`,toggle:O.setDsh}},D=async(e,t)=>{if(!l.value||f.value)return;let n=E[e],r=t?`确定开启 ${n.label} 代理?将改写 ${n.file}(开启前自动备份,关闭时从备份还原)。`:`确定关闭 ${n.label} 代理?将从备份还原 ${n.file}(无备份时移除代理相关配置)。`;try{await T.confirm(r,t?`开启确认`:`关闭确认`,{confirmButtonText:t?`开启`:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{return}f.value=e;try{let e=await n.toggle(t);x.value=e.note??null,S.value=t?`success`:`info`,i(t?`已开启代理`:`已关闭代理`,`success`)}catch(e){i(e.message||`操作失败`,`error`)}finally{f.value=null,await C(!0)}};return(n,i)=>{let c=_(`el-button`),d=_(`el-alert`),T=_(`el-tag`),E=_(`el-switch`),O=_(`el-divider`),k=_(`el-empty`),A=_(`el-card`),j=p(`loading`);return g((m(),e(A,{shadow:`never`},{header:b(()=>[y(`div`,F,[i[7]||=y(`span`,{class:`fw-600`},`代理开关`,-1),t(c,{loading:s.value,onClick:i[0]||=e=>C(!1)},{default:b(()=>[...i[6]||=[a(`刷新`,-1)]]),_:1},8,[`loading`])])]),default:b(()=>[l.value?(m(),r(w,{key:0},[y(`div`,I,` 将本机 CLI 工具的流量一键指向本机网关(`+h(l.value.gatewayBase)+`)。 开启前自动备份原配置为 *.ellm-bak(保留最早的原始备份),关闭时从备份还原。 `,1),x.value?(m(),e(d,{key:0,title:x.value,type:S.value,"show-icon":``,class:`mb-8`,onClose:i[1]||=e=>x.value=null},null,8,[`title`,`type`])):v(``,!0),y(`div`,L,[y(`div`,R,[y(`div`,z,[i[8]||=a(` Claude Code `,-1),t(T,{type:l.value.claudeCode?`success`:`info`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(l.value.claudeCode?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),i[9]||=y(`div`,{class:`switch-desc`},[a(` 写入 `),y(`code`,null,`~/.claude/settings.json`),a(` 的 env.ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN, 鉴权取网关配置的 masterKey(未设置将开启失败);其余字段原样保留,重启 Claude Code 会话后生效。 `)],-1)]),t(E,{"model-value":l.value.claudeCode,loading:f.value===`claudeCode`,onChange:i[2]||=e=>D(`claudeCode`,!!e)},null,8,[`model-value`,`loading`])]),t(O,{class:`switch-divider`}),y(`div`,B,[y(`div`,V,[y(`div`,H,[i[10]||=a(` Codex CLI `,-1),t(T,{type:l.value.codex?`success`:`info`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(l.value.codex?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),i[11]||=y(`div`,{class:`switch-desc`},[a(` 写入 `),y(`code`,null,`~/.codex/config.toml`),a(` 的 model_provider 与 [model_providers.ellm-proxy] 段 (保留用户注释与排版);开启后需按提示设置环境变量 ELLM_PROXY_API_KEY 供 Codex 鉴权。 `)],-1)]),t(E,{"model-value":l.value.codex,loading:f.value===`codex`,onChange:i[3]||=e=>D(`codex`,!!e)},null,8,[`model-value`,`loading`])]),t(O,{class:`switch-divider`}),y(`div`,U,[y(`div`,W,[y(`div`,G,[i[12]||=a(` DeepSeek Harness `,-1),t(T,{type:l.value.dsh?`success`:`info`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(l.value.dsh?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),i[13]||=y(`div`,{class:`switch-desc`},[a(` 写入 `),y(`code`,null,`~/.dsh/settings.yaml`),a(` 的 llm-deepseek.baseURL 与 `),y(`code`,null,`~/.dsh/.credentials.yaml`),a(` 的 DEEPSEEK_API_KEY(取网关 masterKey,未设置则写占位值);模型请在 dsh 内选择与网关部署名一致的模型。 dsh 为 developer preview,配置格式可能随版本变化。 `)],-1)]),t(E,{"model-value":l.value.dsh,loading:f.value===`dsh`,onChange:i[4]||=e=>D(`dsh`,!!e)},null,8,[`model-value`,`loading`])])],64)):(m(),e(k,{key:1,description:u.value||`暂无开关状态`},{default:b(()=>[t(c,{type:`primary`,onClick:i[5]||=e=>C(!1)},{default:b(()=>[...i[14]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`description`]))]),_:1})),[[j,o.value]])}}}),[[`__scopeId`,`data-v-fb084a91`]]);l(),u(),C();var q={class:`service-settings`},J={class:`flex-between`},Y={key:0,class:`switch-row`},ee={class:`switch-info`},te={class:`switch-title`},X={key:0,class:`switch-row`},Z={class:`switch-info`},ne={class:`switch-title`},re={class:`switch-desc`},ie={key:0,class:`version-block`},ae={class:`version-row`},oe={class:`muted-sm`},se={key:0,class:`muted-sm`},ce={key:1,class:`muted-sm`},le={class:`muted-sm`},Q={class:`version-actions`},$=E(n({__name:`ServiceUpdateSettings`,setup(n){let{toast:o}=M(),l=c(!0),u=c(!1),f=c(null),x=c(null),S=c(null),C=c(null),E=c(null),k=c(!1),A=c(!1),j=c(null),F=null;s(()=>F?.abort());let I=async e=>{if(!e){if(u.value)return;u.value=!0}try{let[e,t]=await Promise.allSettled([O.autostart(),O.update()]);f.value=e.status===`fulfilled`?e.value:null,x.value=e.status===`rejected`?e.reason?.message:null,S.value=t.status===`fulfilled`?t.value:null,C.value=t.status===`rejected`?t.reason?.message:null}finally{l.value=!1,u.value=!1}};d(()=>I(!1));let L=i(()=>S.value?.lastCheck?.currentVersion??null),R=i(()=>P(L.value)),z=i(()=>S.value?.lastCheck?.latestVersion??null),B=i(()=>S.value?.lastCheck?.hasUpdate===!0),V=i(()=>{let e=S.value?.lastCheck?.checkedAt;return e?new Date(e).toLocaleString():null}),H=i(()=>{let e=S.value?.lastApply;if(!e)return null;let t=e.appliedAt?new Date(e.appliedAt).toLocaleString():``;return`${e.fromVersion} → ${e.toVersion}${t?`(${t})`:``}`}),U=e=>e?new Date(e).toLocaleString():``,W=async e=>{if(!f.value||E.value)return;let t=e?`确定开启开机自启?将注册登录触发的自启项(登录时自动恢复服务)。`:`确定关闭开机自启?将移除自启项,且此后首次启动不再自动注册。`;try{await T.confirm(t,e?`开启确认`:`关闭确认`,{confirmButtonText:e?`开启`:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{return}E.value=`autostart`;try{let t=await O.setAutostart(e);t.note?o(t.note,`success`):o(e?`开机自启已开启`:`开机自启已关闭`,`success`)}catch(e){o(e.message||`操作失败`,`error`)}finally{E.value=null,await I(!0)}},G=async e=>{if(!S.value||E.value)return;let t=e?`确定开启自动更新?将每小时检查 npm 源,发现新版本自动安装并重启服务。`:`确定关闭自动更新?不再自动检查(手动检查更新不受影响)。`;try{await T.confirm(t,e?`开启确认`:`关闭确认`,{confirmButtonText:e?`开启`:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{return}E.value=`updateEnabled`;try{let t=await O.setUpdateEnabled(e);t.note&&o(t.note,`success`)}catch(e){o(e.message||`操作失败`,`error`)}finally{E.value=null,await I(!0)}},K=async()=>{k.value=!0;try{let e=await O.checkUpdate();j.value=e.hasUpdate?`发现新版本 ${e.latestVersion}(当前 ${e.currentVersion}):点击「立即更新」即可安装(服务自动重启,期间管理台短暂不可访问)`:`已是最新版本 ${e.currentVersion}(检查于 ${U(e.checkedAt)})`,await I(!0)}catch(e){o(e.message||`检查更新失败`,`error`)}finally{k.value=!1}},$=async()=>{try{await T.confirm(`确定更新到 ${z.value}?服务会自动重启并在启动时安装新版本:重启期间管理台短暂不可访问(预计 1~3 分钟),更新完成后自动恢复。`,`更新确认`,{confirmButtonText:`立即更新`,cancelButtonText:`取消`,type:`warning`})}catch{return}A.value=!0;let e=new AbortController;F=e;try{let t=await O.update(),n=await O.applyUpdate();if(!n.updated){j.value=`已是最新版本 ${n.toVersion}`;return}j.value=`正在重启服务并安装 ${n.toVersion}(预计 1~3 分钟):重启期间管理台短暂不可访问,完成后这里会自动显示结果。`;let r=await D({targetVersion:n.toVersion,sinceAppliedAt:t.lastApply?.appliedAt??null,signal:e.signal});if(e.signal.aborted)return;r&&!r.error?(o(`已更新到 ${r.toVersion}`,`success`),j.value=`已更新 ${r.fromVersion} → ${r.toVersion},服务已在新版本上运行。`):r?.error?(o(`更新失败:${r.error}`,`error`),j.value=N(r.error)):j.value=`更新仍在进行(安装耗时较长):稍后刷新页面查看最新状态。`}catch(e){o(e.message||`更新失败`,`error`)}finally{A.value=!1,F===e&&(F=null),e.signal.aborted||await I(!0)}};return(n,i)=>{let o=_(`el-button`),s=_(`el-tag`),c=_(`el-switch`),d=_(`el-empty`),T=_(`el-card`),D=_(`el-link`),O=_(`el-alert`),M=p(`loading`);return g((m(),r(`div`,q,[t(T,{shadow:`never`,class:`mb-16`},{header:b(()=>[y(`div`,J,[i[7]||=y(`span`,{class:`fw-600`},`开机自启`,-1),t(o,{loading:u.value,onClick:i[0]||=e=>I(!1)},{default:b(()=>[...i[6]||=[a(`刷新`,-1)]]),_:1},8,[`loading`])])]),default:b(()=>[f.value?(m(),r(`div`,Y,[y(`div`,ee,[y(`div`,te,[i[8]||=a(` 登录时自动启动服务 `,-1),t(s,{type:f.value.enabled?`success`:`info`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(f.value.enabled?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),i[9]||=y(`div`,{class:`switch-desc`},[a(` 登录操作系统时自动启动服务(无需管理员权限)。 关闭后首次启动 `),y(`code`,null,`ezllm`),a(` 也不会再自动注册,重新开启即可解除。 `)],-1)]),t(c,{"model-value":f.value.enabled,loading:E.value===`autostart`,onChange:i[1]||=e=>W(!!e)},null,8,[`model-value`,`loading`])])):(m(),e(d,{key:1,description:x.value||`暂无自启状态`},{default:b(()=>[t(o,{type:`primary`,onClick:i[2]||=e=>I(!1)},{default:b(()=>[...i[10]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`description`]))]),_:1}),t(T,{shadow:`never`,class:`mb-16`},{header:b(()=>[...i[11]||=[y(`div`,{class:`flex-between`},[y(`span`,{class:`fw-600`},`自动更新`)],-1)]]),default:b(()=>[S.value?(m(),r(`div`,X,[y(`div`,Z,[y(`div`,ne,[i[12]||=a(` 自动检查并安装新版本 `,-1),t(s,{type:S.value.enabled?`success`:`info`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(S.value.enabled?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),y(`div`,re,[S.value.supported?(m(),r(w,{key:1},[a(` 每小时检查 npm 源,发现新版本自动重启服务并在启动时安装(更新期间服务短暂中断); 关闭后仍可在下方手动检查与更新。 `)],64)):(m(),r(w,{key:0},[a(` 当前为源码运行模式,更新功能不可用(仅 npm 全局安装的包支持自动更新)。 `)],64))])]),S.value.supported?(m(),e(c,{key:0,"model-value":S.value.enabled,loading:E.value===`updateEnabled`,onChange:i[3]||=e=>G(!!e)},null,8,[`model-value`,`loading`])):v(``,!0)])):(m(),e(d,{key:1,description:C.value||`暂无更新状态`},{default:b(()=>[t(o,{type:`primary`,onClick:i[4]||=e=>I(!1)},{default:b(()=>[...i[13]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`description`]))]),_:1}),t(T,{shadow:`never`},{header:b(()=>[...i[14]||=[y(`div`,{class:`flex-between`},[y(`span`,{class:`fw-600`},`版本信息`)],-1)]]),default:b(()=>[S.value?(m(),r(`div`,ie,[y(`div`,ae,[i[18]||=y(`span`,{class:`version-label`},`当前版本`,-1),t(s,{size:`small`},{default:b(()=>[a(h(L.value||`未知`),1)]),_:1}),R.value?(m(),e(s,{key:0,type:`warning`,size:`small`,"disable-transitions":``},{default:b(()=>[...i[15]||=[a(`本地构建`,-1)]]),_:1})):v(``,!0),z.value?(m(),r(w,{key:1},[i[17]||=y(`span`,{class:`version-label`},`最新版本`,-1),t(s,{type:B.value?`warning`:`success`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(z.value),1)]),_:1},8,[`type`]),B.value?(m(),e(s,{key:0,type:`warning`,size:`small`,"disable-transitions":``},{default:b(()=>[...i[16]||=[a(`发现新版本`,-1)]]),_:1})):v(``,!0)],64)):v(``,!0)]),y(`div`,oe,[a(` 上次检查:`+h(V.value||`尚未检查`)+` `,1),S.value.updating?(m(),r(w,{key:0},[a(` · 更新执行中...`)],64)):v(``,!0)]),S.value.supported?v(``,!0):(m(),r(`div`,se,`源码运行模式:手动检查与更新不可用。`)),H.value?(m(),r(`div`,ce,`上次更新:`+h(H.value),1)):v(``,!0),y(`div`,le,[i[20]||=a(` npm 包主页:`,-1),t(D,{type:`primary`,href:`https://www.npmjs.com/package/ezllm`,target:`_blank`},{default:b(()=>[...i[19]||=[a(`npmjs.com/package/ezllm`,-1)]]),_:1})]),y(`div`,Q,[t(o,{loading:k.value,disabled:!S.value.supported||S.value.updating,onClick:K},{default:b(()=>[a(h(k.value?`检查中...`:`检查更新`),1)]),_:1},8,[`loading`,`disabled`]),B.value&&S.value.supported?(m(),e(o,{key:0,type:`primary`,loading:A.value,disabled:S.value.updating,onClick:$},{default:b(()=>[a(h(A.value?`更新中...`:`立即更新到 ${z.value}`),1)]),_:1},8,[`loading`,`disabled`])):v(``,!0)]),j.value?(m(),e(O,{key:2,title:j.value,type:`info`,"show-icon":``,class:`mt-8`,onClose:i[5]||=e=>j.value=null},null,8,[`title`])):v(``,!0)])):(m(),e(d,{key:1,description:`更新状态不可用`}))]),_:1})])),[[M,l.value]])}}}),[[`__scopeId`,`data-v-6df6634b`]]);l(),C(),u();var ue={class:`flex-col-gap`},de={class:`flex-between`},fe={class:`muted-sm`},pe={class:`login-row`},me={class:`muted-sm`},he={class:`flex-between`},ge={class:`monitor-row`},_e={class:`save-bar`},ve=E(n({__name:`SettingsView`,setup(n){let{toast:s}=M(),{copyWithToast:l}=j(),u=k(),C=c(`basic`),T=c(!0),E=c(!1),D=c(``),O=async()=>{D.value&&await l(D.value)},N=c(29770),P=c(null),F=c(!0),I=c(``),L=c(``),R=i(()=>D.value.trim()!==``||I.value!==``&&L.value!==``),z=c(!1),B=c(60),V=[{label:`10分钟`,value:10},{label:`30分钟`,value:30},{label:`1小时`,value:60},{label:`2小时`,value:120},{label:`5小时`,value:300},{label:`8小时`,value:480},{label:`12小时`,value:720},{label:`24小时`,value:1440}],{loadError:H,run:U}=A(`设置加载失败,请重试`),W=()=>U(async()=>{try{await u.load(),D.value=u.config.masterKey||``,N.value=u.config.port??29770;let e=u.config[`web-ui`]?.[`login-account`];I.value=e?.username||``,L.value=e?.password||``,F.value=u.config.allowLan!==!1;let t=u.config.latencyTest;z.value=t?.enabled===!0,B.value=t?.intervalMinutes??60;try{let e=await f.get(`/api/status`);P.value=e.listenPort}catch{P.value=null}}finally{T.value=!1}}),G=async()=>{if(I.value.trim()!==``||L.value!==``){if(I.value.trim()===``||L.value===``){s(`用户名和密码需同时填写`,`error`);return}if(L.value.length<6){s(`密码至少 6 位`,`error`);return}}E.value=!0;let e=z.value&&u.config.latencyTest?.enabled!==!0;try{let t=await u.update(e=>{e.masterKey=D.value.trim(),e.port=N.value,e.allowLan=F.value,e.latencyTest={enabled:z.value,intervalMinutes:B.value},e[`web-ui`]??={},e[`web-ui`][`login-account`]??={},e[`web-ui`][`login-account`].username=I.value.trim(),e[`web-ui`][`login-account`].password=L.value});await x(!0),s(`设置已保存并生效`,`success`),e&&s(`已开启自动测试:服务将定期直连所有上游发送探测请求,有少量 token 消耗`,`warning`),t.restartHint&&s(t.restartHint,`warning`)}catch(e){s(e.message,`error`)}finally{E.value=!1}};return d(W),(n,i)=>{let s=_(`el-button`),c=_(`el-alert`),l=_(`el-tag`),u=_(`el-input`),d=_(`el-form-item`),f=_(`el-input-number`),x=_(`el-form`),k=_(`el-card`),A=_(`el-switch`),j=_(`el-divider`),M=_(`el-option`),U=_(`el-select`),q=_(`el-tab-pane`),J=_(`el-tabs`),Y=p(`loading`);return m(),e(J,{modelValue:C.value,"onUpdate:modelValue":i[7]||=e=>C.value=e,class:`settings-tabs`},{default:b(()=>[t(q,{label:`基本设置`,name:`basic`},{default:b(()=>[g((m(),r(`div`,ue,[o(H)?(m(),e(c,{key:0,title:o(H),type:`error`,"show-icon":``,closable:!1},{default:b(()=>[t(s,{size:`small`,onClick:W},{default:b(()=>[...i[8]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):v(``,!0),t(k,{shadow:`never`},{header:b(()=>[y(`div`,de,[i[10]||=y(`span`,{class:`fw-600`},`网关访问`,-1),t(l,{type:`success`},{default:b(()=>[...i[9]||=[a(`运行中`,-1)]]),_:1})])]),default:b(()=>[t(x,{"label-position":`top`},{default:b(()=>[t(d,{label:`API 密钥 (masterKey)`},{default:b(()=>[t(u,{modelValue:D.value,"onUpdate:modelValue":i[0]||=e=>D.value=e,placeholder:`sk-1234`,clearable:``},{append:b(()=>[t(s,{onClick:O},{default:b(()=>[...i[11]||=[a(`复制`,-1)]]),_:1})]),_:1},8,[`modelValue`]),i[12]||=y(`div`,{class:`muted-sm`},`客户端请求 /v1/* 时的认证密钥(Bearer <masterKey>;留空 = 本地放行)`,-1)]),_:1}),t(d,{label:`监听端口 (port)`},{default:b(()=>[t(f,{modelValue:N.value,"onUpdate:modelValue":i[1]||=e=>N.value=e,min:1,max:65535,step:1,style:{width:`220px`}},null,8,[`modelValue`]),y(`div`,fe,[i[14]||=a(` 网关与管理台 API 的监听端口,保存后重启生效 `,-1),P.value===null?v(``,!0):(m(),r(w,{key:0},[i[13]||=a(` ;服务上报的端口 `,-1),y(`b`,null,h(P.value),1)],64))])]),_:1})]),_:1})]),_:1}),t(k,{shadow:`never`},{header:b(()=>[...i[15]||=[y(`span`,{class:`fw-600`},`安全与登录`,-1)]]),default:b(()=>[t(x,{"label-position":`top`},{default:b(()=>[t(d,{label:`管理台登录账号`},{default:b(()=>[y(`div`,pe,[t(u,{modelValue:I.value,"onUpdate:modelValue":i[2]||=e=>I.value=e,placeholder:`用户名`,style:{width:`200px`}},null,8,[`modelValue`]),t(u,{modelValue:L.value,"onUpdate:modelValue":i[3]||=e=>L.value=e,type:`password`,placeholder:`密码(至少 6 位)`,"show-password":``,style:{width:`200px`}},null,8,[`modelValue`])]),i[16]||=y(`div`,{class:`muted-sm`},` 管理台登录凭证;留空 = 免登录直接访问(仅本机使用时推荐)。 修改后立即生效,需用新账号重新登录 `,-1)]),_:1}),t(d,{label:`允许局域网访问 (allowLan)`},{default:b(()=>[t(A,{modelValue:F.value,"onUpdate:modelValue":i[4]||=e=>F.value=e},null,8,[`modelValue`]),y(`div`,me,[i[17]||=a(` 开启 = 绑定全部网卡,局域网内设备可访问;关闭 = 仅本机 127.0.0.1。保存后需重启生效 `,-1),R.value?v(``,!0):(m(),r(w,{key:0},[a(` ;未设置任何凭据(密钥与登录账号皆无)时始终仅绑本机 `)],64))])]),_:1})]),_:1})]),_:1}),t(k,{shadow:`never`},{header:b(()=>[y(`div`,he,[i[18]||=y(`span`,{class:`fw-600`},`模型服务监控`,-1),t(l,{type:z.value?`success`:`info`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(z.value?`已开启`:`未开启`),1)]),_:1},8,[`type`])])]),default:b(()=>[y(`div`,ge,[i[19]||=y(`div`,{class:`monitor-info`},[y(`div`,{class:`monitor-title`},`自动测试模型服务状态`),y(`div`,{class:`muted-sm`},` 按设定间隔自动直连所有上游模型发送极小探测请求(max_tokens: 1,有少量 token 消耗); 测试结果展示在「服务状态」页面 `)],-1),t(A,{modelValue:z.value,"onUpdate:modelValue":i[5]||=e=>z.value=e},null,8,[`modelValue`])]),z.value?(m(),r(w,{key:0},[t(j,{style:{margin:`12px 0`}}),t(x,{"label-position":`top`},{default:b(()=>[t(d,{label:`测试间隔`,style:{"margin-bottom":`0`}},{default:b(()=>[t(U,{modelValue:B.value,"onUpdate:modelValue":i[6]||=e=>B.value=e,style:{width:`220px`}},{default:b(()=>[(m(),r(w,null,S(V,e=>t(M,{key:e.value,label:e.label,value:e.value},null,8,[`label`,`value`])),64))]),_:1},8,[`modelValue`]),i[20]||=y(`div`,{class:`muted-sm`},`自动测试的执行间隔,保存后即时生效(无需重启)`,-1)]),_:1})]),_:1})],64)):v(``,!0)]),_:1}),y(`div`,_e,[t(s,{type:`primary`,size:`large`,loading:E.value,disabled:E.value||o(H)!==null,onClick:G},{default:b(()=>[a(h(E.value?`保存中...`:`保存设置`),1)]),_:1},8,[`loading`,`disabled`])])])),[[Y,T.value]])]),_:1}),t(q,{label:`代理开关`,name:`harness`,lazy:``},{default:b(()=>[t(K)]),_:1}),t(q,{label:`服务与更新`,name:`service`,lazy:``},{default:b(()=>[t($)]),_:1})]),_:1},8,[`modelValue`])}}}),[[`__scopeId`,`data-v-e5f93ad5`]]);export{ve as default};
@@ -0,0 +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,Z as c,a as l,et as u,ft as d,it as f,j as p,k as m,m as h,mt as g,n as _,r as v,u as y,vt as b}from"./router-Oh7GPjpX.js";import{t as x}from"./message-CYCqk4yf.js";import{t as S}from"./index-kwJNWvLc.js";import{t as C}from"./clipboard-JYWVdyjq.js";s(),h(),b();var w={class:`setup-wrap`},T={class:`account-row`},E=S(n({__name:`SetupView`,setup(n){let s=y(),h=o(!1),b=o(``),S=!1,E=o(``),D=o(``),O=o(!1),k=o(``);c(async()=>{!(await _()).masterKeySet&&h.value&&A()});function A(){b.value=j(),S=!0}d(h,e=>{e?b.value.trim()===``&&A():S&&=(b.value=``,!1)});function j(){let e=new Uint8Array(32);crypto.getRandomValues(e);let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}async function M(){await C(b.value)?x.success(`已复制到剪贴板`):x.error(`复制失败,请手动选择复制`)}async function N(){k.value=``;let e=h.value?`server`:`local`,t=b.value.trim(),n=E.value.trim()!==``||D.value!==``;if(h.value&&t===``){k.value=`服务器部署必须设置主密钥,防止 /v1 网关被他人盗用`;return}if(h.value&&!n){k.value=`服务器部署必须设置登录账号密码,防止管理台被陌生人登录`;return}if(n){if(E.value.trim()===``||D.value===``){k.value=`用户名和密码需同时填写`;return}if(D.value.length<6){k.value=`密码至少 6 位`;return}}O.value=!0;try{let r=t===``?null:await l.post(`/api/setup/master-key`,{mode:`custom`,masterKey:t}),i=await l.post(`/api/setup/finish`,{deployment:e,...n?{username:E.value.trim(),password:D.value}:{}});v(e,n),x.success(n?`初始化完成,请使用新账号登录`:`初始化完成,免登录进入管理台`);let a=r?.restartHint??i.restartHint;a&&x({message:a,type:`warning`,duration:8e3}),await s.push(n?`/login`:`/`)}catch(e){k.value=e.message||`保存失败`}finally{O.value=!1}}return(n,o)=>{let s=f(`el-checkbox`),c=f(`el-alert`),l=f(`el-button`),d=f(`el-input`),_=f(`el-form-item`),v=f(`el-form`),y=f(`el-card`);return u(),r(`div`,w,[t(y,{shadow:`never`,class:`setup-card`},{default:g(()=>[o[10]||=m(`div`,{class:`setup-brand`},[m(`span`,{class:`brand-mark`},`EZ`),m(`span`,{class:`setup-title`},`初始化 EZLLM`)],-1),o[11]||=m(`p`,{class:`setup-sub`},`首次使用前完成部署形态与访问凭据的配置`,-1),t(s,{modelValue:h.value,"onUpdate:modelValue":o[0]||=e=>h.value=e,class:`mb-16`},{default:g(()=>[...o[4]||=[i(` 允许其他设备访问本服务(局域网 / 公网部署) `,-1)]]),_:1},8,[`modelValue`]),h.value?(u(),e(c,{key:0,type:`warning`,"show-icon":``,closable:!1,title:`服务将对网络中的其他设备可见,请务必保留主密钥并修改默认账号`,class:`mb-16`})):p(``,!0),t(v,{"label-position":`top`,onSubmit:a(N,[`prevent`])},{default:g(()=>[t(_,null,{label:g(()=>[...o[5]||=[i(` API 主密钥(本地部署可留空) `,-1),m(`span`,{class:`label-hint`},`调用 /v1/* 时的 Bearer Token;留空 = 不启用鉴权,且未设登录账号时服务仅本机可访问`,-1)]]),default:g(()=>[t(d,{modelValue:b.value,"onUpdate:modelValue":o[1]||=e=>b.value=e,placeholder:`已设置主密钥,留空保持不变`,clearable:``},{append:g(()=>[t(l,{onClick:A},{default:g(()=>[...o[6]||=[i(`生成`,-1)]]),_:1}),t(l,{disabled:!b.value,onClick:M},{default:g(()=>[...o[7]||=[i(`复制`,-1)]]),_:1},8,[`disabled`])]),_:1},8,[`modelValue`])]),_:1}),t(_,null,{label:g(()=>[...o[8]||=[i(` 管理台登录(可选) `,-1),m(`span`,{class:`label-hint`},`不填 = 免登录直接进管理台(纯本机使用);勾选上方后必须填写`,-1)]]),default:g(()=>[m(`div`,T,[t(d,{modelValue:E.value,"onUpdate:modelValue":o[2]||=e=>E.value=e,placeholder:`用户名`,clearable:``},null,8,[`modelValue`]),t(d,{modelValue:D.value,"onUpdate:modelValue":o[3]||=e=>D.value=e,type:`password`,"show-password":``,placeholder:`密码(至少 6 位)`},null,8,[`modelValue`])])]),_:1}),k.value?(u(),e(c,{key:0,title:k.value,type:`error`,"show-icon":``,closable:!1,class:`mb-16`},null,8,[`title`])):p(``,!0),t(l,{type:`primary`,class:`full-width`,loading:O.value,onClick:N},{default:g(()=>[...o[9]||=[i(` 完成初始化 `,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1})])}}}),[[`__scopeId`,`data-v-d6e5e69a`]]);export{E as default};
@@ -0,0 +1 @@
1
+ .setup-wrap[data-v-d6e5e69a]{justify-content:center;align-items:center;min-height:100vh;display:flex}.setup-card[data-v-d6e5e69a]{border-radius:16px;width:520px;max-width:92vw;box-shadow:0 12px 40px #1f23291a}.setup-brand[data-v-d6e5e69a]{justify-content:center;align-items:center;gap:10px;margin-top:8px;display:flex}.setup-title[data-v-d6e5e69a]{color:var(--el-text-color-primary);font-size:20px;font-weight:700}.setup-sub[data-v-d6e5e69a]{text-align:center;color:var(--el-text-color-secondary);margin:6px 0 24px;font-size:13px}.account-row[data-v-d6e5e69a]{gap:12px;width:100%;display:flex}.label-hint[data-v-d6e5e69a]{color:#909399;font-size:12px;font-weight:400;line-height:1.4;display:block}.full-width[data-v-d6e5e69a]{width:100%}.mb-16[data-v-d6e5e69a]{margin-bottom:16px}
@@ -0,0 +1 @@
1
+ import{O as e,Tt as t,V as n,a as r,vt as i}from"./router-Oh7GPjpX.js";import{r as a}from"./index-kwJNWvLc.js";i(),n();var o=a(`config`,()=>{let n=t({}),i=t(!1),a=e(()=>Array.isArray(n.value.providers)?n.value.providers:[]),o=e(()=>a.value.length),s=e(()=>a.value.reduce((e,t)=>e+(t.models?.length??0),0));async function c(){i.value=!0;try{n.value=await r.get(`/api/config`)}finally{i.value=!1}}async function l(){return await r.put(`/api/config`,n.value)}async function u(e){return e(n.value),await l()}return{config:n,loading:i,providers:a,providerCount:o,totalModelCount:s,load:c,save:l,update:u}});export{o as t};