waygate-open 1.6.14 → 1.6.16
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.
- package/README.md +3 -3
- package/package.json +1 -1
- package/server/dist/api/overview.service.js +9 -0
- package/server/dist/proxy/quota/quota-parse.js +9 -4
- package/server/dist/version.js +1 -1
- package/server/package.json +1 -1
- package/web/dist/assets/{ApiKeysPage-LOAdUyHT.js → ApiKeysPage-Ck0Gry6E.js} +3 -3
- package/web/dist/assets/{ClientMetricTip-D-pXFJpS.js → ClientMetricTip-C2VuiT4-.js} +1 -1
- package/web/dist/assets/ClientsPage-Dy68uQDl.js +1 -0
- package/web/dist/assets/LandingPage-B2hMgbmZ.css +1 -0
- package/web/dist/assets/LandingPage-P2QNDFaP.js +15 -0
- package/web/dist/assets/OverviewPage-BgBo_XhF.js +1 -0
- package/web/dist/assets/RequestsPage-CVB0wpCH.js +5 -0
- package/web/dist/assets/{Select-BxZGnteq.js → Select-G6AhT0TA.js} +1 -1
- package/web/dist/assets/SettingsPage-B4Mew-7b.js +5 -0
- package/web/dist/assets/UsagePage-cxZ-GnpO.js +1 -0
- package/web/dist/assets/index-CEoe20BF.css +1 -0
- package/web/dist/assets/index-nQeRK3kW.js +2 -0
- package/web/dist/assets/sharedWindow-FDfq75PI.js +1 -0
- package/web/dist/index.html +2 -2
- package/web/dist/assets/ClientsPage-D3z8xy1H.js +0 -1
- package/web/dist/assets/LandingPage-BXVLs2Ni.js +0 -15
- package/web/dist/assets/LandingPage-DIP_XFhP.css +0 -1
- package/web/dist/assets/OverviewPage-xTsnlyEP.js +0 -1
- package/web/dist/assets/RequestsPage-B2ThbdoO.js +0 -5
- package/web/dist/assets/SettingsPage-CfuPWZ4_.js +0 -3
- package/web/dist/assets/UsagePage-UatftkHb.js +0 -1
- package/web/dist/assets/index-BtuqaoxX.css +0 -1
- package/web/dist/assets/index-VH6Gc3-s.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{J as e,S as t,it as n,k as r,m as i,q as a,r as o,rt as s,tt as c}from"./vendor-befEYGHM.js";import{
|
|
1
|
+
import{J as e,S as t,it as n,k as r,m as i,q as a,r as o,rt as s,tt as c}from"./vendor-befEYGHM.js";import{a as l}from"./index-nQeRK3kW.js";var u=c();function d({tone:e=`ghost`,dot:t=!1,children:n}){return(0,u.jsxs)(`span`,{className:`pill pill-${e}`,children:[t?(0,u.jsx)(`span`,{className:`dot dot-live`}):null,n]})}function f({tone:e=`off`,children:t}){return(0,u.jsx)(`span`,{className:`tag tag-${e}`,children:t})}function p({title:e,status:t,actions:n}){return(0,u.jsxs)(`div`,{className:`topbar`,children:[(0,u.jsxs)(`div`,{className:`topbar-left`,children:[(0,u.jsx)(`h1`,{children:e}),t]}),n?(0,u.jsx)(`div`,{className:`topbar-right`,children:n}):null]})}function m({title:e,aside:t,children:n,className:r=``,padded:i=!0}){return(0,u.jsxs)(`div`,{className:`card${i?` panel`:``} ${r}`.trim(),children:[e?(0,u.jsxs)(`div`,{className:`panel-head`,style:i?void 0:{padding:`18px 20px 0`,marginBottom:12},children:[(0,u.jsx)(`h3`,{children:e}),t]}):null,n]})}function h({items:e}){return(0,u.jsx)(`div`,{className:`statbar`,"data-count":e.length,children:e.map(e=>(0,u.jsxs)(`div`,{children:[(0,u.jsxs)(`div`,{className:`sb-top`,children:[(0,u.jsx)(`span`,{className:`lb`,children:e.label}),e.detail?(0,u.jsx)(`span`,{className:`sdl`,children:e.detail}):null]}),e.tip?(0,u.jsx)(l,{content:e.tip,placement:e.tipPos===`down`?`below`:`auto`,className:`tooltip-value-anchor`,children:(0,u.jsx)(`div`,{className:`vl`,style:e.tone===`live`?{color:`var(--signal-live)`}:e.tone===`amber`?{color:`var(--warn-amber)`}:void 0,children:e.value})}):(0,u.jsx)(`div`,{className:`vl`,style:e.tone===`live`?{color:`var(--signal-live)`}:e.tone===`amber`?{color:`var(--warn-amber)`}:void 0,children:e.value})]},e.label))})}function g({label:e,value:t,detail:n,tone:r,icon:i,tip:a,tipPos:o}){let s=r===`cyan`||r===`violet`||r===`green`||r===`amber`||r===`blue`||r===`rose`?` m-${r}`:``;return(0,u.jsxs)(`div`,{className:`card metric`,children:[(0,u.jsxs)(`div`,{className:`m-top`,children:[i?(0,u.jsx)(`span`,{className:`m-ico${s}`,"aria-hidden":`true`,children:i}):null,(0,u.jsx)(`span`,{className:`lb`,children:e})]}),a?(0,u.jsx)(l,{content:a,placement:o===`down`?`below`:`auto`,className:`tooltip-value-anchor`,children:(0,u.jsx)(`div`,{className:`vl`,children:t})}):(0,u.jsx)(`div`,{className:`vl`,children:t}),n?(0,u.jsx)(`div`,{className:`dl${r===`up`?` up`:r===`warn`?` warn`:``}`,children:n}):null]})}function _({kind:e,title:n,detail:a,onRetry:s,children:c}){return e===`loading`?(0,u.jsxs)(`div`,{className:`state-block`,role:`status`,"aria-live":`polite`,"aria-busy":`true`,children:[(0,u.jsx)(t,{size:22,className:`spin`,style:{animation:`spin 1s linear infinite`}}),(0,u.jsx)(`div`,{className:`t`,children:n??`加载中…`})]}):e===`empty`?(0,u.jsxs)(`div`,{className:`state-block`,role:`status`,"aria-live":`polite`,children:[(0,u.jsx)(r,{size:26}),(0,u.jsx)(`div`,{className:`t`,children:n??`暂无数据`}),a?(0,u.jsx)(`div`,{className:`d`,children:a}):null,c]}):(0,u.jsxs)(`div`,{className:`state-block`,role:`alert`,"aria-live":`assertive`,children:[(0,u.jsx)(o,{size:26}),(0,u.jsx)(`div`,{className:`t`,children:n??`加载失败`}),a?(0,u.jsx)(`div`,{className:`d`,children:a}):null,s?(0,u.jsxs)(`button`,{type:`button`,className:`btn btn-quiet btn-sm`,onClick:s,children:[(0,u.jsx)(i,{size:14}),`重试`]}):null]})}function v(e){if(!e)return``;let t={40001:`有字段没通过校验,回退一步检查刚填的内容。`,40002:`确认文字不匹配 —— 这是刻意设计的门槛。`,40101:`管理口令不正确,注意区分大小写。`,40102:`会话已过期,登录后继续。`,40290:`登录失败次数过多,请 ${e.retryAfterSeconds?Math.ceil(e.retryAfterSeconds/60):10} 分钟后重试。`,40301:`请求来源校验失败(CSRF 防护),刷新页面重试。`,40401:`这条记录已不存在,可能刚被删掉了。`,40901:`同名密钥已存在,换一个名字。`,50001:`服务端未分类异常,可稍后重试或查看服务日志。`,50301:`数据库暂时不可用,确认后端进程是否在运行。`};return(e.code===40001||e.code===50001)&&/[\u4e00-\u9fa5]/.test(e.message)?e.message:t[e.code]?t[e.code]:e.status===0?e.message:e.message||`请求失败(HTTP ${e.status})`}var y=n(),b=s();function x({value:t,options:n,onChange:r,width:i,disabled:o,size:s=`md`,ariaLabel:c}){let[l,d]=(0,y.useState)(!1),[f,p]=(0,y.useState)(0),[m,h]=(0,y.useState)(null),[g,_]=(0,y.useState)(!1),v=(0,y.useRef)(null),x=(0,y.useRef)(null),S=(0,y.useRef)({buf:``,at:0}),C=(0,y.useId)(),w=`${C}list`,T=e=>`${C}opt${e}`,E=Math.max(0,n.findIndex(e=>e.value===t)),D=(0,y.useCallback)(()=>{let e=v.current;if(!e)return;let t=e.getBoundingClientRect();h({left:t.left,top:t.top,bottom:t.bottom,width:t.width})},[]),O=(0,y.useCallback)(()=>{o||n.length===0||(S.current={buf:``,at:0},p(E),D(),d(!0))},[o,D,n.length,E]),k=(0,y.useCallback)(e=>{let t=n[e];t&&r(t.value),d(!1),v.current?.focus()},[r,n]);(0,y.useLayoutEffect)(()=>{l&&x.current?.focus()},[l]),(0,y.useLayoutEffect)(()=>{if(!l||!m)return;let e=x.current;if(!e)return;let t=window.innerHeight-m.bottom;_(t<e.offsetHeight+12&&m.top>t)},[l,m,n.length]),(0,y.useEffect)(()=>{l&&x.current?.querySelector(`[data-opt="${f}"]`)?.scrollIntoView({block:`nearest`})},[f,l]),(0,y.useEffect)(()=>{if(!l)return;let e=()=>D(),t=e=>{let t=e.target;t&&(v.current?.contains(t)||x.current?.contains(t))||d(!1)};return window.addEventListener(`scroll`,e,!0),window.addEventListener(`resize`,e),document.addEventListener(`pointerdown`,t,!0),()=>{window.removeEventListener(`scroll`,e,!0),window.removeEventListener(`resize`,e),document.removeEventListener(`pointerdown`,t,!0)}},[l,D]);let A=(0,y.useCallback)((e,t)=>{let r=Date.now(),i=(r-S.current.at>700?``:S.current.buf)+e;S.current={buf:i,at:r};let a=i.toLowerCase(),o=n.length,s=i.length===1?(t+1)%o:0;for(let e=0;e<o;e+=1){let t=(s+e)%o;if(n[t].label.toLowerCase().startsWith(a)){p(t);return}}},[n]),j=e=>e.key.length===1&&!e.ctrlKey&&!e.metaKey&&!e.altKey&&/\S/.test(e.key),M=e=>{if(!(o||l)){if(e.key===`ArrowDown`||e.key===`ArrowUp`||e.key===`Enter`||e.key===` `){e.preventDefault(),O();return}j(e)&&(e.preventDefault(),O(),A(e.key,E))}},N=e=>{let t=n.length;switch(e.key){case`ArrowDown`:e.preventDefault(),p(e=>(e+1)%t);break;case`ArrowUp`:e.preventDefault(),p(e=>(e-1+t)%t);break;case`Home`:e.preventDefault(),p(0);break;case`End`:e.preventDefault(),p(t-1);break;case`Enter`:case` `:e.preventDefault(),k(f);break;case`Escape`:e.preventDefault(),e.stopPropagation(),d(!1),v.current?.focus();break;case`Tab`:d(!1),v.current?.focus();break;default:j(e)&&A(e.key,f)}},P=n[E]?.label??``;return(0,u.jsxs)(`div`,{className:`sel-field`,style:i?{width:i}:void 0,children:[(0,u.jsxs)(`button`,{type:`button`,ref:v,className:s===`sm`?`sel sm`:`sel`,"aria-haspopup":`listbox`,"aria-expanded":l,"aria-controls":l?w:void 0,"aria-label":c,"data-value":t,disabled:o,onClick:()=>l?d(!1):O(),onKeyDown:M,children:[(0,u.jsx)(`span`,{className:`sel-val`,children:P}),(0,u.jsx)(a,{size:s===`sm`?12:13,className:`ic caret-glyph`,"aria-hidden":!0})]}),l&&m?(0,b.createPortal)((0,u.jsx)(`div`,{ref:x,id:w,role:`listbox`,tabIndex:-1,"aria-activedescendant":n.length?T(f):void 0,className:s===`sm`?`sel-pop sm`:`sel-pop`,onKeyDown:N,style:{left:Math.max(8,Math.min(m.left,window.innerWidth-Math.max(m.width,168)-8)),top:g?void 0:m.bottom+6,bottom:g?window.innerHeight-m.top+6:void 0,minWidth:m.width},children:n.map((n,r)=>(0,u.jsxs)(`div`,{id:T(r),"data-opt":r,"data-value":n.value,role:`option`,"aria-selected":n.value===t,className:`sel-opt${r===f?` on`:``}${n.value===t?` picked`:``}`,onMouseEnter:()=>p(r),onPointerDown:e=>e.preventDefault(),onClick:()=>k(r),children:[(0,u.jsx)(`span`,{className:`sel-opt-lb`,children:n.label}),n.value===t?(0,u.jsx)(e,{size:13,className:`ic`,"aria-hidden":!0}):null]},n.value))}),document.body):null]})}export{m as a,d as c,g as i,f as l,_ as n,h as o,v as r,p as s,x as t};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{D as e,J as t,S as n,f as r,it as i,l as a,p as o,tt as s,w as c,z as l}from"./vendor-befEYGHM.js";import{M as u,a as d,c as f,g as p,j as m,p as h,r as g}from"./index-nQeRK3kW.js";import{t as _}from"./accessUrl-DbL5DLDz.js";import{a as v,c as y,l as b,n as x,r as S,s as C,t as w}from"./Select-G6AhT0TA.js";import{t as T}from"./Modal-B-rIrvXS.js";import{t as E}from"./Drawer-CleQGhRU.js";import{t as D}from"./Switch-0KA1AbiV.js";var O=i(),k=s();function A({item:e,value:t,disabled:n,onChange:r}){if(e.type===`switch`)return(0,k.jsx)(D,{checked:!!t,disabled:n||e.readonly,label:e.label,onChange:e=>r(e)});if(e.type===`badge`)return(0,k.jsx)(b,{tone:`live`,children:String(t)});if(e.type===`select`){let i=(e.options??[]).map(e=>({value:e.value,label:e.label}));return(0,k.jsx)(w,{value:String(t),options:i,disabled:n||e.readonly,onChange:e=>r(e),width:188})}return e.type===`number`?(0,k.jsx)(`input`,{className:`field-input num`,type:`number`,value:t==null?``:String(t),disabled:n||e.readonly,onChange:e=>r(e.target.value===``?``:Number(e.target.value)),"aria-label":e.label}):e.type===`mapping`?null:(0,k.jsx)(`input`,{className:`field-input text`,value:t==null?``:String(t),disabled:n||e.readonly,onChange:e=>r(e.target.value),"aria-label":e.label})}function j(){let e=_(),[n,r]=(0,O.useState)(!1),i=async()=>{try{await navigator.clipboard.writeText(e),r(!0),window.setTimeout(()=>r(!1),1200)}catch{}};return(0,k.jsxs)(`div`,{className:`card access-card`,children:[(0,k.jsxs)(`div`,{className:`access-head`,children:[(0,k.jsxs)(`span`,{className:`access-title`,children:[(0,k.jsx)(c,{size:13,"aria-hidden":!0}),`接入地址`]}),(0,k.jsx)(`span`,{className:`access-sub`,children:`客户端与 API 同源 —— 这就是你当前访问控制台的地址`})]}),(0,k.jsxs)(`div`,{className:`key-plain access-url`,children:[(0,k.jsx)(`code`,{children:e}),(0,k.jsxs)(`button`,{type:`button`,className:`copy`,"aria-label":n?`已复制接入地址`:`复制接入地址`,onClick:()=>void i(),children:[n?(0,k.jsx)(t,{size:13}):(0,k.jsx)(l,{size:13}),n?`已复制`:`复制`]})]}),(0,k.jsxs)(`p`,{className:`chain-note`,children:[`客户端里要填两组值:`,(0,k.jsx)(`b`,{children:`base_url`}),` 就是上面这串;`,(0,k.jsx)(`b`,{children:`API Key`}),` 用你在本页`,(0,k.jsx)(`b`,{children:`新建的那把`}),(0,k.jsx)(`span`,{className:`code-chip`,children:`sk-waygate-…`}),`(明文只在创建时显示一次,丢了只能删掉重建)。`]}),(0,k.jsxs)(`div`,{className:`cred-note access-cert`,children:[(0,k.jsx)(a,{size:14,"aria-hidden":!0}),(0,k.jsxs)(`span`,{children:[`本服务的 TLS 是`,(0,k.jsx)(`b`,{children:`自签证书`}),`:客户端得先信任它的根证书,否则会以「证书错误」失败 —— 那`,(0,k.jsx)(`b`,{children:`不是`}),`地址填错。把根证书装进系统信任库,或让客户端通过`,(0,k.jsx)(`span`,{className:`code-chip`,children:`NODE_EXTRA_CA_CERTS`}),` /`,(0,k.jsx)(`span`,{className:`code-chip`,children:`SSL_CERT_FILE`}),`指向随部署产出的`,(0,k.jsx)(`span`,{className:`code-chip`,children:`relay-ca.crt`}),`。`]})]})]})}var M=8,N=128;function P({onClose:r,onDone:i}){let[o,s]=(0,O.useState)(`reset`),[c,d]=(0,O.useState)(`warn`),[p,m]=(0,O.useState)(``),[h,_]=(0,O.useState)(!1),[v,y]=(0,O.useState)(null),[b,x]=(0,O.useState)(null),[C,w]=(0,O.useState)(!1),[E,D]=(0,O.useState)(``),[A,j]=(0,O.useState)(``),[P,I]=(0,O.useState)(null),L=p===`确认`,R=async()=>{if(L&&!h){_(!0),y(null);try{let e=await f.resetAdminPassword();x(e),d(`result`)}catch(e){y(e instanceof u?S(e):String(e))}finally{_(!1)}}},z=async()=>{if(b)try{await navigator.clipboard.writeText(b.password),w(!0),window.setTimeout(()=>w(!1),2e3)}catch{y(`浏览器拒绝了剪贴板访问,请手动选中口令复制。`)}},B=()=>{x(null),D(``),j(``),i?.(),r()},V=async()=>{if(h)return;let e=E.trim();if(e.length===0){y(`管理口令不能为空或纯空白。`);return}if(e.length<M){y(`管理口令至少 ${M} 个字符,当前 ${e.length} 个。`);return}if(E.length>N){y(`管理口令最多 ${N} 个字符,当前 ${E.length} 个。`);return}if(E!==A){y(`两次输入不一致,请重新确认。`);return}_(!0),y(null);try{let e=await f.setAdminPassword(E);D(``),j(``),I(e.persisted?`已生效,下次登录用新口令。当前会话不受影响。`:`已生效(仅内存),下次登录用新口令 —— 但服务端数据库不可写,重启后会回到上一个口令。`)}catch(e){y(e instanceof u?S(e):String(e))}finally{_(!1)}};if(o===`manual`&&P)return(0,k.jsxs)(T,{title:`管理口令已更新`,onClose:B,footer:(0,k.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,onClick:B,children:`知道了`}),children:[(0,k.jsx)(`div`,{className:`pw-note`,children:P}),(0,k.jsxs)(`p`,{className:`ov-sub`,style:{marginTop:12},children:[`服务端只存了口令的 scrypt 哈希,`,(0,k.jsx)(`b`,{children:`回不出明文`}),`。请确保你已经记住了刚才输入的口令。`]})]});if(o===`manual`){let t=E.trim().length>0&&E.trim().length<M,i=A.length>0&&E!==A;return(0,k.jsxs)(T,{title:`手动设定管理口令`,onClose:r,footer:(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`button`,{type:`button`,className:`btn btn-quiet btn-sm`,onClick:r,children:`取消`}),(0,k.jsxs)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,disabled:h||t||i||E.trim().length===0,onClick:()=>void V(),children:[h?(0,k.jsx)(n,{size:14}):(0,k.jsx)(e,{size:14}),h?`保存中…`:`保存并生效`]})]}),children:[(0,k.jsxs)(`p`,{className:`ov-sub`,children:[`设定一个你自己方便记忆的管理口令(至少 `,M,` 个字符)。 保存后`,(0,k.jsx)(`b`,{children:`立即生效、无需重启`}),`,当前会话不会被打断。`]}),(0,k.jsxs)(`div`,{className:`ov-field`,children:[(0,k.jsx)(`label`,{htmlFor:`pw-new`,children:`新管理口令`}),(0,k.jsx)(`input`,{id:`pw-new`,type:`password`,className:`field-input text`,style:{width:`100%`},value:E,autoFocus:!0,autoComplete:`new-password`,placeholder:`至少 ${M} 个字符`,onChange:e=>{D(e.target.value),y(null)}}),t?(0,k.jsxs)(`div`,{className:`ov-hint`,style:{color:`var(--warn-amber)`},children:[`至少 `,M,` 个字符,当前 `,E.trim().length,` 个。`]}):null]}),(0,k.jsxs)(`div`,{className:`ov-field`,children:[(0,k.jsx)(`label`,{htmlFor:`pw-new-confirm`,children:`再次输入`}),(0,k.jsx)(`input`,{id:`pw-new-confirm`,type:`password`,className:`field-input text`,style:{width:`100%`},value:A,autoComplete:`new-password`,placeholder:`重复上面输入的口令`,onChange:e=>{j(e.target.value),y(null)}}),i?(0,k.jsx)(`div`,{className:`ov-hint`,style:{color:`var(--warn-amber)`},children:`两次输入不一致。`}):null]}),(0,k.jsxs)(`div`,{className:`ov-lose`,children:[(0,k.jsx)(`b`,{children:`请记住它:`}),`设定后旧口令立即失效,且本产品没有「忘记口令」的找回通道。 口令明文不会保存在浏览器任何位置,也不会被回显。`]}),v?(0,k.jsx)(g,{tone:`error`,children:(0,k.jsx)(`span`,{style:{display:`block`,marginTop:14},children:v})}):null]})}return c===`result`&&b?(0,k.jsxs)(T,{title:`新管理口令`,onClose:B,footer:(0,k.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,onClick:B,children:`我已保存,关闭`}),children:[(0,k.jsxs)(`div`,{className:`pw-once`,children:[(0,k.jsxs)(`div`,{className:`pw-once-head`,children:[(0,k.jsx)(a,{size:16}),(0,k.jsx)(`b`,{children:`这是唯一一次显示`})]}),(0,k.jsx)(`div`,{className:`pw-once-body`,children:`关闭这个窗口后,服务端也回不出这份明文 —— 库里只存了它的 scrypt 哈希。 请现在就复制并保存到你的密码管理器里。`})]}),(0,k.jsxs)(`div`,{className:`pw-plain`,children:[(0,k.jsx)(`code`,{children:b.password}),(0,k.jsxs)(`button`,{type:`button`,className:`btn btn-quiet btn-sm`,onClick:()=>void z(),children:[C?(0,k.jsx)(t,{size:14}):(0,k.jsx)(l,{size:14}),C?`已复制`:`复制`]})]}),b.persisted?(0,k.jsxs)(`div`,{className:`pw-note`,children:[`已写入服务端数据库,`,(0,k.jsx)(`b`,{children:`立即生效、无需重启`}),`,并会随每日备份一起保存。 下次登录请使用新口令。`]}):(0,k.jsx)(g,{tone:`warn`,children:(0,k.jsxs)(`span`,{style:{display:`block`,marginTop:14},children:[`服务端数据库不可写,新口令`,(0,k.jsx)(`b`,{children:`仅本次运行有效`}),`:重启后会回到旧口令。 请先修好数据目录权限,再重置一次。`]})}),v?(0,k.jsx)(g,{tone:`error`,children:(0,k.jsx)(`span`,{style:{display:`block`,marginTop:14},children:v})}):null]}):c===`confirm`?(0,k.jsxs)(T,{title:`确认重置管理口令?`,onClose:r,footer:(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,onClick:r,children:`取消(保持现状)`}),(0,k.jsxs)(`button`,{type:`button`,className:`btn btn-danger btn-sm`,disabled:!L||h,onClick:()=>void R(),children:[h?(0,k.jsx)(n,{size:14}):null,h?`重置中…`:`确认重置`]})]}),children:[(0,k.jsxs)(`p`,{className:`ov-sub`,children:[`重置后,`,(0,k.jsx)(`b`,{children:`当前口令立即失效`}),`。你正在使用的这个会话不会被打断,但下次登录必须用新口令。`]}),(0,k.jsxs)(`div`,{className:`ov-lose`,children:[(0,k.jsx)(`b`,{children:`会失去什么:`}),`旧口令的所有副本(笔记、密码管理器里的旧条目)都会变成无效值。本产品没有「忘记口令」的找回通道。`]}),(0,k.jsxs)(`div`,{className:`ov-field`,children:[(0,k.jsxs)(`label`,{htmlFor:`pw-confirm`,children:[`输入 `,(0,k.jsx)(`b`,{style:{color:`var(--text-secondary)`,fontWeight:500},children:`确认`}),` 以继续`]}),(0,k.jsx)(`input`,{id:`pw-confirm`,className:`field-input text`,style:{width:`100%`,fontFamily:`var(--font-mono)`},value:p,autoFocus:!0,placeholder:`确认`,onChange:e=>m(e.target.value)}),(0,k.jsx)(`div`,{className:`ov-hint`,children:`打错一个字就没法继续。重置入口凭证值得这一步。`})]}),v?(0,k.jsx)(g,{tone:`error`,children:v}):null]}):(0,k.jsxs)(T,{title:`重置管理口令`,onClose:r,footer:(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`button`,{type:`button`,className:`btn btn-quiet btn-sm`,onClick:r,children:`取消`}),(0,k.jsxs)(`button`,{type:`button`,className:`btn btn-danger btn-sm`,onClick:()=>d(`confirm`),children:[(0,k.jsx)(e,{size:14}),`我明白,继续`]})]}),children:[(0,k.jsx)(F,{mode:o,onChange:e=>{s(e),y(null)}}),(0,k.jsxs)(`p`,{className:`ov-sub`,children:[`服务端会生成一个新的 16 位随机口令。`,(0,k.jsx)(`b`,{children:`新口令只显示一次`}),`,请准备好记录工具。`]}),(0,k.jsxs)(`div`,{className:`pw-warn-list`,children:[(0,k.jsxs)(`div`,{children:[(0,k.jsx)(`span`,{className:`pw-dot`}),(0,k.jsxs)(`span`,{children:[(0,k.jsx)(`b`,{children:`当前口令立即失效`}),` —— 但已登录的会话`,(0,k.jsx)(`b`,{children:`不受影响`}),`:会话由独立密钥 (RELAY_SECRET)签名,与口令本身无关。包括其它浏览器标签页在内的登录态, 都会保持有效直到各自过期。本版本未提供「改密强制所有会话下线」。`]})]}),(0,k.jsxs)(`div`,{children:[(0,k.jsx)(`span`,{className:`pw-dot`}),(0,k.jsxs)(`span`,{children:[(0,k.jsx)(`b`,{children:`没有找回通道`}),` —— 忘记新口令后,只能上服务器删除数据结构后重新引导。`]})]}),(0,k.jsxs)(`div`,{children:[(0,k.jsx)(`span`,{className:`pw-dot`}),(0,k.jsxs)(`span`,{children:[(0,k.jsx)(`b`,{children:`立即生效、无需重启`}),` —— 哈希写进数据库后立刻对后续登录起作用。`]})]})]}),(0,k.jsx)(`div`,{className:`ov-hint`,style:{marginTop:12},children:`想用自己的口令?切到上方「手动设定」—— 随机口令更安全,手动口令更好记,按需选择。`})]})}function F({mode:e,onChange:t}){return(0,k.jsxs)(`span`,{className:`seg-tabs`,role:`group`,"aria-label":`口令变更方式`,style:{marginBottom:14},children:[(0,k.jsx)(`button`,{type:`button`,className:e===`reset`?`on`:``,"aria-pressed":e===`reset`,onClick:()=>t(`reset`),children:`随机重置`}),(0,k.jsx)(`button`,{type:`button`,className:e===`manual`?`on`:``,"aria-pressed":e===`manual`,onClick:()=>t(`manual`),children:`手动设定`})]})}function I({spec:e,onClose:t,onDone:r}){let[i,a]=(0,O.useState)(``),[o,s]=(0,O.useState)(!1),[c,l]=(0,O.useState)(null),d=i===`确认`,p=async()=>{if(d&&!o){s(!0),l(null);try{r(await f.danger(e.action,i))}catch(e){l(e instanceof u?e:new u(String(e),0,0)),s(!1)}}};return(0,k.jsxs)(T,{title:e.title,onClose:t,footer:(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,onClick:t,children:`取消(保持现状)`}),(0,k.jsxs)(`button`,{type:`button`,className:`btn btn-danger btn-sm`,disabled:!d||o,onClick:()=>void p(),children:[o?(0,k.jsx)(n,{size:14}):null,o?`执行中…`:e.ok]})]}),children:[(0,k.jsx)(`p`,{className:`ov-sub`,children:e.body}),(0,k.jsxs)(`div`,{className:`ov-lose`,children:[(0,k.jsx)(`b`,{children:`会失去什么:`}),e.lose]}),(0,k.jsxs)(`div`,{className:`ov-field`,children:[(0,k.jsxs)(`label`,{htmlFor:`danger-confirm`,children:[`输入 `,(0,k.jsx)(`b`,{style:{color:`var(--text-secondary)`,fontWeight:500},children:`确认`}),` 以继续`]}),(0,k.jsx)(`input`,{id:`danger-confirm`,className:`field-input text`,style:{width:`100%`,fontFamily:`var(--font-mono)`},value:i,autoFocus:!0,placeholder:`确认`,onChange:e=>a(e.target.value)}),(0,k.jsx)(`div`,{className:`ov-hint`,children:`打错一个字就没法继续。破坏性操作值得这一步。`})]}),c?(0,k.jsx)(g,{tone:`error`,children:S(c)}):null]})}var L={"danger.clearLogs":{action:`clearLogs`,title:`清空全部日志?`,body:`删除后「按模型 / 按客户端」明细会一并归零。剩余积分不受影响,服务也不中断。`,lose:`将删除本机全部请求日志,覆盖保留天数内的所有记录,没有备份入口。`,ok:`确认清空`},"danger.resetKeys":{action:`resetKeys`,title:`重置全部密钥?`,body:`所有密钥会立即失效,每个客户端都要重新填一次。已消耗的积分不受影响。`,lose:`将失效全部 sk-waygate- 密钥,正在使用它们的客户端会立刻收到 401。`,ok:`确认重置`},"danger.restoreDefaults":{action:`restoreDefaults`,title:`恢复默认配置?`,body:`会用默认值覆盖 ~/.relay/config.yml。你改过的端口、并发、日志保留天数都会回到出厂值。`,lose:`将覆盖所有自定义配置,服务重启后生效。`,ok:`确认恢复`}},R={openai:`OpenAI 方言`,anthropic:`Anthropic 方言`,qoder:`COSY 协议`};function z(){let e=m(()=>f.providers(),[],{cacheKey:`providers`}),t=e.data?.items??[],[n,r]=(0,O.useState)(null),i=m(()=>f.providerGrowthPanel(n.id),[n?.id],{enabled:n!==null});return(0,k.jsxs)(v,{title:`提供商健康`,aside:(0,k.jsxs)(y,{children:[t.length,` 家 · 只读总览`]}),children:[e.initial&&e.loading?(0,k.jsx)(`div`,{className:`empty-note`,style:{padding:`8px 0`},children:`正在读取提供商…`}):e.error?(0,k.jsx)(`div`,{className:`empty-note`,style:{padding:`8px 0`},children:`提供商列表没取到,稍后重试。`}):t.length===0?(0,k.jsx)(`div`,{className:`empty-note`,style:{padding:`8px 0`},children:`还没有登记任何提供商 —— 到「提供商管理 → 提供商」新增。`}):(0,k.jsx)(`div`,{className:`tbl-scroll`,children:(0,k.jsxs)(`table`,{className:`tbl`,children:[(0,k.jsx)(`caption`,{className:`sr-only`,children:`各提供商的健康状态`}),(0,k.jsx)(`thead`,{children:(0,k.jsxs)(`tr`,{children:[(0,k.jsx)(`th`,{scope:`col`,children:`提供商`}),(0,k.jsx)(`th`,{scope:`col`,children:`协议`}),(0,k.jsx)(`th`,{scope:`col`,children:`凭证`}),(0,k.jsx)(`th`,{scope:`col`,children:`状态`}),(0,k.jsx)(`th`,{scope:`col`,className:`r`,children:`模型数`}),(0,k.jsx)(`th`,{scope:`col`,children:`积分 / 签到`})]})}),(0,k.jsx)(`tbody`,{children:t.map(e=>(0,k.jsxs)(`tr`,{children:[(0,k.jsx)(`td`,{className:`td-strong`,children:e.name}),(0,k.jsx)(`td`,{className:`td-sub`,children:R[e.protocol]??e.protocol}),(0,k.jsx)(`td`,{children:(0,k.jsx)(`span`,{className:`up-badge${e.configured?``:` warn`}`,children:e.configured?`有效`:`未配置`})}),(0,k.jsx)(`td`,{children:e.active?(0,k.jsx)(y,{tone:`live`,children:`已启用`}):(0,k.jsx)(y,{tone:`ghost`,children:`未启用`})}),(0,k.jsx)(`td`,{className:`r td-mono`,children:p(e.modelCount??0)}),(0,k.jsx)(`td`,{className:`td-sub td-mono`,children:e.credits?.available?(0,k.jsxs)(k.Fragment,{children:[`剩余 `,h(e.credits.remaining??0),e.credits.consumed===null?null:(0,k.jsxs)(k.Fragment,{children:[` `,(0,k.jsx)(d,{content:`已消耗 / 累计发放 —— 账户级全部历史(含官方客户端直连的用量)。
|
|
2
|
+
不是本服务转发的那部分,与剩余不是同一种量。`,children:(0,k.jsxs)(`span`,{className:`credit-aside`,children:[`已消耗 `,h(e.credits.consumed),e.credits.granted===null?``:` / 发放 ${h(e.credits.granted)}`]})})]}),e.credits.stale?`(偏旧)`:``]}):e.qoderCredits?(0,k.jsxs)(k.Fragment,{children:[e.qoderCredits.remaining===null?`余额未知`:`剩余 ${h(e.qoderCredits.remaining)}`,e.qoderCredits.lifetimeConsumed!==null&&e.qoderCredits.lifetimeConsumed!==void 0?(0,k.jsxs)(k.Fragment,{children:[` `,(0,k.jsx)(d,{content:`累计消耗 —— 这个账号近一年在该平台消耗掉的 credits 总量(账号级)。
|
|
3
|
+
它不是当前余额,也不是本服务转发的那部分:含官方客户端直连的用量。
|
|
4
|
+
数值等于每日消耗热力图近 371 天之和。`,children:(0,k.jsxs)(`span`,{className:`credit-aside`,children:[`累计消耗 `,h(e.qoderCredits.lifetimeConsumed),e.qoderCredits.granted===null?``:` / 发放 ${h(e.qoderCredits.granted)}`]})})]}):null,e.qoderCredits.stale?`(偏旧)`:``,e.signin?.streak?`(连续活跃 ${p(e.signin.streak)} 天)`:``]}):e.wbCredits?(0,k.jsxs)(k.Fragment,{children:[`剩余 `,h(e.wbCredits.remaining??0),e.wbCredits.consumed===null?null:(0,k.jsxs)(k.Fragment,{children:[` `,(0,k.jsx)(d,{content:`已消耗 / 累计发放 —— 账户全部资源包的历史合计(含已过期包、
|
|
5
|
+
含官方客户端直连的用量)。剩余只统计未过期包,两者口径不同。`,children:(0,k.jsxs)(`span`,{className:`credit-aside`,children:[`已消耗 `,h(e.wbCredits.consumed),e.wbCredits.granted===null?``:` / 发放 ${h(e.wbCredits.granted)}`]})})]}),e.wbSignin?.streak?`(连签 ${p(e.wbSignin.streak)} 天)`:``]}):e.signin?.checkedOn?(0,k.jsxs)(k.Fragment,{children:[`今日已签到`,e.signin.lastPoints?` +${p(e.signin.lastPoints)}`:``]}):e.wbSignin?.checkedOn?(0,k.jsxs)(k.Fragment,{children:[`今日已签到`,e.wbSignin.lastPoints?` +${p(e.wbSignin.lastPoints)}`:``]}):`—`}),(0,k.jsx)(`td`,{children:e.protocol===`openai`&&e.wbOAuth?.configured?(0,k.jsx)(d,{content:`查看成长任务的完成情况(进度/奖励/状态,只读)`,children:(0,k.jsx)(`button`,{type:`button`,className:`mini-pill`,onClick:()=>r(e),children:`任务`})}):(0,k.jsx)(`span`,{className:`td-sub`,children:`—`})})]},e.id))})]})}),(0,k.jsxs)(`ul`,{className:`ph-notes`,children:[(0,k.jsxs)(`li`,{children:[(0,k.jsx)(`b`,{children:`积分口径(三家各不同)`}),`:本表「积分」列都取`,(0,k.jsx)(`b`,{children:`上游真实余额`}),`,非本地推算。 MiniMax Code 来自 `,(0,k.jsx)(`span`,{className:`code-chip`,children:`credit/details`}),`(余额/已用/累计发放齐全,精确到 0.01); WorkBuddy 来自资源包聚合 `,(0,k.jsx)(`span`,{className:`code-chip`,children:`get-user-resource`}),`(剩余/发放为包级真实数); Qoder CN 来自 `,(0,k.jsx)(`span`,{className:`code-chip`,children:`v2/me/usage`}),`(套餐内 + 资源包合计 —— 签到赠送的 Credits 进资源包,故签完此处会上涨)。`,(0,k.jsx)(`b`,{children:`到期时刻仅 Qoder 不提供`}),`(上游无此字段), 概览「积分账本」对应列显示 `,(0,k.jsx)(`span`,{className:`code-chip`,children:`—`}),`。 另一种「累计消耗」是`,(0,k.jsx)(`b`,{children:`账号级近一年消耗总量`}),`(含官方客户端直连),与余额不是一回事, 两者不混算。`]}),(0,k.jsxs)(`li`,{children:[(0,k.jsx)(`b`,{children:`每日签到`}),`:MiniMax Code 由本服务每天 08:05 后自动代签(OAuth 链)。WorkBuddy 分两档: 已导入桌面端 OAuth 凭证的(提供商管理 → 提供商 → 导入OAuth)每天 08:05 `,(0,k.jsx)(`b`,{children:`自动代领`}),`签到 + 成长任务 + 连登兑换;未导入的只做状态同步(上游不允许 API 密钥代领,403 实证)。 OAuth 与转发用的 API 密钥互不影响(实验实证多会话共存,桌面端不受干扰)。成长任务的 完成情况点本表「任务」查看(未完成的需在官方客户端真实使用后才能领)。`]}),(0,k.jsxs)(`li`,{children:[(0,k.jsx)(`b`,{children:`凭证口径(两家不同)`}),`:`,(0,k.jsx)(`b`,{children:`MiniMax Code 是真互斥`}),` —— refresh token 一次性,且「同一账号同时只有一个有效会话」, 桌面客户端登录会把本服务顶下线,反之亦然;`,(0,k.jsx)(`b`,{children:`建议给本服务用专用账号`}),`。`,(0,k.jsx)(`b`,{children:`Qoder CN 不互斥`}),` —— 支持多会话并存,本服务与桌面客户端可同时用同一账号(实测 2026-10-16),`,(0,k.jsx)(`b`,{children:`无需`}),`专用账号。任一凭证失效时到「提供商管理 → 提供商」重新导入。`]}),(0,k.jsxs)(`li`,{children:[(0,k.jsx)(`b`,{children:`Qoder 零内容断流自动重试`}),`:Qoder 网关在大上下文时偶发「返回 200 但零字节即断开」, 本服务会自动重发一次(最多 1 次,对客户端无感 —— 重试发生在响应提交之前)。 请求日志里记 `,(0,k.jsx)(`span`,{className:`code-chip`,children:`retry_count`}),` 与 `,(0,k.jsx)(`span`,{className:`code-chip`,children:`retried`}),`。`]}),(0,k.jsxs)(`li`,{children:[(0,k.jsx)(`b`,{children:`提供商归属的已知限制`}),`:请求表不记录「这条走的是哪家」,提供商归属按`,(0,k.jsx)(`b`,{children:`模型 id → 目录`}),`推断。因此同名的模型 id 分属两家时归属可能不准; 请求日志的「提供商」列也是用同一推断口径。`]})]}),n?(0,k.jsx)(E,{title:`成长任务 · ${n.name}`,subtitle:`完成态与奖励(上游实时只读;未完成的需在官方客户端真实使用后才能领)`,onClose:()=>r(null),children:(0,k.jsxs)(`div`,{className:`drawer-body`,children:[i.initial&&i.loading?(0,k.jsx)(`div`,{className:`empty-note`,children:`正在读取任务面板…`}):i.error||!i.data?.ok?(0,k.jsx)(`div`,{className:`empty-note`,children:i.error?.message??i.data?.message??`任务面板没取到,稍后重试。`}):(0,k.jsx)(`div`,{style:{maxHeight:`min(68vh, 640px)`,overflow:`auto`},children:(0,k.jsxs)(`table`,{className:`tbl`,style:{minWidth:480},children:[(0,k.jsx)(`caption`,{className:`sr-only`,children:`成长任务完成情况`}),(0,k.jsx)(`thead`,{children:(0,k.jsxs)(`tr`,{children:[(0,k.jsx)(`th`,{scope:`col`,children:`任务`}),(0,k.jsx)(`th`,{scope:`col`,style:{width:56},children:`进度`}),(0,k.jsx)(`th`,{scope:`col`,className:`r`,style:{width:84},children:`奖励`}),(0,k.jsx)(`th`,{scope:`col`,style:{width:72},children:`状态`})]})}),(0,k.jsx)(`tbody`,{children:i.data.tasks.map(e=>(0,k.jsxs)(`tr`,{children:[(0,k.jsx)(`td`,{style:{maxWidth:104},children:(0,k.jsx)(d,{content:e.desc?`${e.title??e.code} —— ${e.desc}`:e.title??e.code,children:(0,k.jsx)(`span`,{className:`td-strong`,style:{display:`inline-block`,maxWidth:`100%`,whiteSpace:`nowrap`,overflow:`hidden`,textOverflow:`ellipsis`,verticalAlign:`bottom`},children:e.title??e.code})})}),(0,k.jsx)(`td`,{className:`td-mono`,children:e.progress?`${e.progress.current}/${e.progress.target}`:`—`}),(0,k.jsx)(`td`,{className:`r td-mono`,children:e.rewardCredit?`${e.rewardCredit} 积分`:`—`}),(0,k.jsx)(`td`,{children:e.status===`claimed`?(0,k.jsx)(y,{tone:`live`,children:`已领取`}):e.status===`in_progress`?(0,k.jsx)(y,{tone:`amber`,children:`进行中`}):e.locked?(0,k.jsx)(y,{tone:`ghost`,children:`未解锁`}):(0,k.jsx)(y,{tone:`ghost`,children:`待完成`})})]},e.code))})]})}),(0,k.jsx)(`div`,{className:`footer-note`,children:`每天 08:05 自动代领一轮(签到 + 已完成的任务 + 连登兑换);这里的数据来自上游任务面板,实时只读。`})]})}):null]})}var B=new Set([`credential.source`,`credential.status`]),V={service:`ghost`,credential:`cyan`,quota:`amber`,limits:`rose`,logs:`ghost`,password:`amber`,danger:`amber`,mapping:`cyan`};function H(){let t=m(()=>f.settings(),[],{cacheKey:`settings`}),[n,i]=(0,O.useState)({}),[a,s]=(0,O.useState)(!1),[c,l]=(0,O.useState)(null),[d,p]=(0,O.useState)(null),[h,_]=(0,O.useState)(null),[b,w]=(0,O.useState)(null),[T,E]=(0,O.useState)(!1),[D,A]=(0,O.useState)(null),[M,N]=(0,O.useState)(`access`),F=t.data?.groups??[],R=(0,O.useMemo)(()=>{let e=[{id:`access`,label:`接入地址`,tone:`cyan`}];for(let t of F)t.id!==`mapping`&&e.push({id:t.id,label:t.label,tone:V[t.id]??`ghost`});return e.push({id:`password`,label:`管理口令`,tone:`amber`}),e.push({id:`mapping`,label:`键位映射`,tone:`cyan`}),e},[F]),H=(0,O.useMemo)(()=>{let e={};for(let t of F){let r=0;for(let e of t.items)B.has(e.key)||e.readonly||e.type===`action`||e.type===`mapping`||e.key in n&&n[e.key]!==e.value&&(r+=1);r>0&&(e[t.id]=r)}return e},[F,n]),W=(e,t)=>e in n?n[e]:t,G=(0,O.useMemo)(()=>{if(!t.data)return[];let e=[];return t.data.groups.forEach(t=>t.items.forEach(t=>{B.has(t.key)||t.readonly||t.type===`action`||t.type===`mapping`||t.key in n&&n[t.key]!==t.value&&e.push({key:t.key,value:n[t.key]})})),e},[t.data,n]),K=async()=>{if(!(G.length===0||a)){s(!0),l(null),p(null);try{let e=await f.putSettings(G);i({}),p(e.requiresRestart?`已应用 ${e.applied} 项,配置版本 → v${e.version}。其中含需重启才生效的项。`:`已应用 ${e.applied} 项,配置版本 → v${e.version}。`),setTimeout(()=>p(null),4e3),t.reload()}catch(e){l(e instanceof u?e:new u(String(e),0,0))}finally{s(!1)}}},q=e=>{let n=e.affected.logs??e.affected.keys??0;w(`操作已完成,影响 ${n} 条记录。`),setTimeout(()=>w(null),4e3),_(null),t.reload()},J=F.find(e=>e.id===`mapping`)?.items[0],Y=F.find(e=>e.id===M),X=F.find(e=>e.id===`danger`)?.items??[];return(0,k.jsxs)(`div`,{className:`view on`,children:[(0,k.jsx)(C,{title:`设置`,status:t.data?(0,k.jsx)(y,{tone:G.length?`amber`:`ghost`,dot:G.length>0,children:G.length?`${G.length} 项待保存`:`配置版本 v${t.data.version}`}):null,actions:(0,k.jsxs)(k.Fragment,{children:[G.length?(0,k.jsxs)(`button`,{type:`button`,className:`btn btn-quiet btn-sm`,onClick:()=>i({}),children:[(0,k.jsx)(o,{size:14}),`放弃改动`]}):null,(0,k.jsxs)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,disabled:G.length===0||a,onClick:()=>void K(),children:[(0,k.jsx)(r,{size:14}),a?`保存中…`:`保存`]})]})}),(0,k.jsxs)(`div`,{className:`view-body stack`,children:[c?(0,k.jsx)(g,{tone:`error`,children:S(c)}):null,d?(0,k.jsx)(g,{tone:`success`,children:d}):null,b?(0,k.jsx)(g,{tone:`success`,children:b}):null,D?(0,k.jsx)(g,{tone:`success`,children:D}):null,(0,k.jsxs)(`div`,{className:`settings-split`,children:[(0,k.jsx)(`nav`,{className:`settings-nav`,"aria-label":`设置分组`,children:R.map(e=>{let t=H[e.id]??0;return(0,k.jsxs)(`button`,{type:`button`,className:`settings-nav-i${M===e.id?` on`:``}`,"aria-current":M===e.id?`page`:void 0,onClick:()=>N(e.id),children:[(0,k.jsx)(`span`,{className:`settings-nav-label`,children:e.label}),t>0?(0,k.jsx)(`span`,{className:`settings-nav-dirty`,children:t}):null]},e.id)})}),(0,k.jsx)(`div`,{className:`settings-content`,children:t.initial&&t.loading?(0,k.jsx)(v,{children:(0,k.jsx)(x,{kind:`loading`,title:`正在读取配置…`})}):t.error?(0,k.jsx)(v,{children:(0,k.jsx)(x,{kind:`error`,title:`配置没取到`,detail:S(t.error),onRetry:t.reload})}):(0,k.jsxs)(k.Fragment,{children:[M===`access`?(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(j,{}),(0,k.jsx)(z,{})]}):null,M===`password`?(0,k.jsxs)(`div`,{className:`card`,children:[(0,k.jsxs)(`div`,{className:`group-head`,children:[(0,k.jsxs)(`h3`,{children:[(0,k.jsx)(e,{size:14,style:{verticalAlign:-2,marginRight:6}}),`管理口令`]}),(0,k.jsx)(`p`,{children:`控制台的唯一入口凭证`})]}),(0,k.jsxs)(`div`,{className:`set-row`,children:[(0,k.jsxs)(`div`,{className:`info`,children:[(0,k.jsx)(`b`,{children:`管理口令`}),(0,k.jsxs)(`span`,{children:[`两种改法:`,(0,k.jsx)(`b`,{children:`随机重置`}),`由服务端生成 16 位新口令(更强,但需当场保存);`,(0,k.jsx)(`b`,{children:`手动设定`}),`由你输入一个方便记忆的口令(至少 8 个字符)。 两种都立即生效、无需重启;新口令不回显、不落浏览器任何位置。`]})]}),(0,k.jsx)(`div`,{className:`ctl`,children:(0,k.jsxs)(`button`,{type:`button`,className:`btn btn-quiet btn-sm`,disabled:a,onClick:()=>E(!0),children:[(0,k.jsx)(e,{size:13}),`修改`]})})]})]}):null,M===`danger`?(0,k.jsxs)(`div`,{className:`card danger-zone`,children:[(0,k.jsxs)(`div`,{className:`group-head`,children:[(0,k.jsx)(`h3`,{style:{color:`var(--warn-amber)`},children:`危险操作`}),(0,k.jsx)(`p`,{children:`不可撤销,需二次确认`})]}),X.map(e=>(0,k.jsxs)(`div`,{className:`set-row`,children:[(0,k.jsxs)(`div`,{className:`info`,children:[(0,k.jsx)(`b`,{children:e.label}),(0,k.jsx)(`span`,{children:e.why})]}),(0,k.jsx)(`div`,{className:`ctl`,children:(0,k.jsx)(`button`,{type:`button`,className:`mini-pill danger`,disabled:a,onClick:()=>_(L[e.key]??null),children:e.label})})]},e.key))]}):null,M===`mapping`&&J?.type===`mapping`?(0,k.jsxs)(v,{title:J.label,aside:(0,k.jsx)(y,{children:`config.yml`}),children:[(0,k.jsx)(`div`,{className:`code`,style:{fontSize:12},children:Object.entries(J.value??{}).map(([e,t])=>(0,k.jsxs)(`div`,{children:[(0,k.jsx)(`span`,{className:`k`,children:e}),` → `,(0,k.jsx)(`span`,{className:`st`,children:t})]},e))}),(0,k.jsx)(`div`,{className:`footer-note`,children:J.why})]}):null,Y&&Y.id!==`danger`&&Y.id!==`mapping`?(0,k.jsx)(U,{group:Y,saving:a,valueOf:W,onChange:(e,t)=>i(n=>({...n,[e]:t}))}):null]})})]})]}),h?(0,k.jsx)(I,{spec:h,onClose:()=>_(null),onDone:q}):null,T?(0,k.jsx)(P,{onClose:()=>E(!1),onDone:()=>{A(`管理口令已更新并立即生效。下次登录请使用新口令。`),setTimeout(()=>A(null),4e3),t.reload()}}):null]})}function U({group:e,saving:t,valueOf:n,onChange:r}){let i=e.items.filter(e=>!B.has(e.key));if(i.length===0)return null;let a=i.filter(e=>!e.noop),o=i.filter(e=>e.noop);return(0,k.jsxs)(`div`,{className:`card`,children:[(0,k.jsxs)(`div`,{className:`group-head`,children:[(0,k.jsx)(`h3`,{children:e.label}),(0,k.jsx)(`p`,{children:W(e.id)})]}),a.map(e=>(0,k.jsx)(G,{item:e,value:n(e.key,e.value),saving:t,onChange:t=>r(e.key,t)},e.key)),o.length>0?(0,k.jsxs)(`details`,{className:`dormant`,children:[(0,k.jsxs)(`summary`,{children:[o.length,` 项暂未生效`,(0,k.jsx)(`span`,{children:`改了不会有任何变化 —— 依赖的功能未实现或上游未供货`})]}),o.map(e=>(0,k.jsx)(G,{item:e,value:n(e.key,e.value),saving:t,onChange:t=>r(e.key,t)},e.key))]}):null]})}function W(e){return{service:`进程监听与启动方式`,credential:`跨提供商的全局策略(部分项仅对 WorkBuddy 生效)`,quota:`积分口径与额度轮询(仅 WorkBuddy;MiniMax 走独立账本,Qoder 无端点)`,signin:`每日 08:05 自动签到(WorkBuddy 可关;MiniMax 恒开,Qoder 无签到)`,limits:`自用场景的保护,而非配额限制`,logs:`留在本机,不参与同步`}[e]??``}function G({item:e,value:t,saving:n,onChange:r}){return(0,k.jsxs)(`div`,{className:`set-row`,children:[(0,k.jsxs)(`div`,{className:`info`,children:[(0,k.jsxs)(`b`,{children:[e.label,e.requiresRestart?(0,k.jsx)(`span`,{style:{marginLeft:8,fontSize:10.5,color:`var(--warn-amber)`},children:`需重启`}):null]}),(0,k.jsx)(`span`,{children:e.why})]}),(0,k.jsx)(`div`,{className:`ctl`,children:(0,k.jsx)(A,{item:e,value:t,disabled:n,onChange:r})})]})}export{H as SettingsPage};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{A as e,E as t,it as n,r,tt as i}from"./vendor-befEYGHM.js";import{O as a,_ as o,a as s,c,g as l,j as u,k as d,p as f,u as p,v as m,x as h}from"./index-nQeRK3kW.js";import{a as g,c as _,n as v,o as y,r as b,s as x,t as S}from"./Select-G6AhT0TA.js";import{a as C}from"./PageSkeleton-DG-Dj4_9.js";import{n as w,t as T}from"./sharedWindow-FDfq75PI.js";import{t as E}from"./useFx-xcrp_LHB.js";import{n as D,r as O,t as k}from"./ClientMetricTip-C2VuiT4-.js";var A=n(),j=i(),M={tokens:`消耗 tokens`,requests:`请求次数`};function N({points:e,metric:t,avg:n}){let[r,i]=(0,A.useState)(null),[a,o]=(0,A.useState)(null),s=(0,A.useRef)(null),c=(0,A.useRef)(null),[u,d]=(0,A.useState)(null);(0,A.useLayoutEffect)(()=>{let t=c.current,n=s.current;if(!t||!n||r===null||e.length===0){d(null);return}let i=()=>{let i=(r+.5)/e.length*n.clientWidth,a=n.getBoundingClientRect(),o=t.getBoundingClientRect(),s=i-(o.left-a.left);d(Math.max(12,Math.min(s,o.width-12)))};return i(),window.addEventListener(`resize`,i),()=>window.removeEventListener(`resize`,i)},[r,t,e.length]);let f=(0,A.useMemo)(()=>e.map((n,r)=>{let i=r>0?e[r-1]:null,a=i?t===`tokens`?n.tokens-i.tokens:n.requests-i.requests:null,o=/T\d{2}$/.test(n.bucket),s=(n.models??[]).slice(0,5).map(e=>`${e.model} ${h(e.tokens)} tokens`).join(`、`),c=a===null?``:` · 较${o?`上一小时`:`昨日`} ${a>0?`增加`:a<0?`减少`:`持平`}${a===0?``:` ${l(Math.abs(a))}`}`;return`${p(n.bucket)} · ${l(n.requests)} 次请求 · ${h(n.tokens)} tokens`+(n.errors>0?` · ${l(n.errors)} 次失败`:``)+(s?` · 模型:${s}`:``)+c}),[e,t]);if(e.length===0)return(0,j.jsx)(`div`,{className:`empty-note`,style:{padding:`24px 0`},children:`该窗口内没有请求记录。`});let m=e.map(e=>t===`tokens`?e.tokens:e.requests),g=Math.max(1,...m),_=l,v=n===null?null:Math.round(Math.min(1,Math.max(0,n/g))*1e4)/1e4,y=Math.ceil(e.length/5),b=a??e.length-1,x=t=>{let n=e.length-1,r;if(t.key===`ArrowRight`)r=Math.min(n,b+1);else if(t.key===`ArrowLeft`)r=Math.max(0,b-1);else if(t.key===`Home`)r=0;else if(t.key===`End`)r=n;else return;t.preventDefault(),o(r),i(r),(s.current?.querySelector(`[data-idx="${r}"]`)??void 0)?.focus()},S=r===null?null:e[r],C=S?/T\d{2}$/.test(S.bucket):!1,w=S&&r!==null&&r>0?e[r-1]:null,T=S&&w?t===`tokens`?S.tokens-w.tokens:S.requests-w.requests:null;return(0,j.jsxs)(j.Fragment,{children:[(0,j.jsxs)(`div`,{className:`avgline`,style:{"--avg":v??0},children:[v===null?null:(0,j.jsxs)(`span`,{className:`avg-row`,children:[(0,j.jsxs)(`span`,{className:`avg-tag`,children:[`日均 `,_(n)]}),(0,j.jsx)(`i`,{className:`avg-rule`})]}),(0,j.jsxs)(`div`,{className:`bars30 js-grow`,ref:s,onKeyDown:x,onMouseLeave:()=>i(null),children:[(0,j.jsxs)(`span`,{className:`grid`,"aria-hidden":`true`,children:[(0,j.jsx)(`i`,{className:`base`}),(0,j.jsx)(`i`,{className:`mid`}),(0,j.jsx)(`i`,{className:`q1`})]}),e.map((n,a)=>{let o=t===`tokens`?n.tokens:n.requests,s=a===e.length-1?`today`:o>=g?`peak`:``,c=n.errors>0,l=f[a];return(0,j.jsx)(`div`,{"data-idx":a,className:`bcol${a===r?` on`:``}`,role:`img`,"aria-label":l,tabIndex:a===b?0:-1,onMouseEnter:()=>i(a),onFocus:()=>i(a),onBlur:()=>i(e=>e===a?null:e),children:(0,j.jsx)(`div`,{className:`b ${s}`.trim()+(c?` err`:``),style:{height:`${Math.max(2,Math.round(o/g*100))}%`},children:c?(0,j.jsx)(`span`,{className:`err-dot`,"aria-hidden":`true`}):null})},n.bucket)}),S?(()=>{let n=r!==null&&e.length>0?(r+.5)/e.length*100:50;return(0,j.jsxs)(`div`,{ref:c,className:`bar-tip${n<12?` tip-left`:n>88?` tip-right`:``}`,style:{"--tip-x":`${n}%`,"--tip-arrow":u===null?void 0:`${u}px`},"aria-hidden":`true`,children:[(0,j.jsxs)(`div`,{className:`bt-head`,children:[(0,j.jsx)(`b`,{children:p(S.bucket)}),r===e.length-1?(0,j.jsx)(`span`,{className:`bt-tag`,children:`最新`}):null]}),(0,j.jsxs)(`div`,{className:`bt-row${t===`tokens`?` hot`:``}`,children:[(0,j.jsx)(`span`,{children:`消耗 tokens`}),(0,j.jsx)(`i`,{children:h(S.tokens)})]}),(S.models??[]).length>0?(0,j.jsx)(`div`,{className:`bt-models`,children:(S.models??[]).map(e=>(0,j.jsxs)(`div`,{className:`bt-model`,children:[(0,j.jsx)(`span`,{className:`bt-model-name`,children:e.model}),(0,j.jsxs)(`i`,{children:[h(e.tokens),(0,j.jsx)(`em`,{children:` · ${S.tokens>0?Math.round(e.tokens/S.tokens*100):0}%`})]})]},e.model))}):null,(0,j.jsxs)(`div`,{className:`bt-row${t===`requests`?` hot`:``}`,children:[(0,j.jsx)(`span`,{children:`请求次数`}),(0,j.jsx)(`i`,{children:l(S.requests)})]}),S.errors>0?(0,j.jsxs)(`div`,{className:`bt-row bt-err`,children:[(0,j.jsx)(`span`,{children:`失败`}),(0,j.jsxs)(`i`,{children:[l(S.errors),(0,j.jsxs)(`em`,{children:[` `,`(`,l(S.requests)===`--`||S.requests===0?`—`:`${(S.errors/S.requests*100).toFixed(1)}%`,`)`]})]})]}):null,T===null?null:(0,j.jsxs)(`div`,{className:`bt-delta${T>0?` up`:T<0?` down`:` flat`}`,children:[`较`,C?`上一小时`:`昨日`,T>0?` ▲`:T<0?` ▼`:` — `,T>0||T<0?l(Math.abs(T)):`持平`]})]})})():null]})]}),(0,j.jsx)(`div`,{className:`axis`,children:e.map((t,n)=>(0,j.jsx)(`span`,{children:n%y===0||n===e.length-1?p(t.bucket):``},t.bucket))})]})}function P({items:e,windowLabel:t}){if(e.length===0)return(0,j.jsxs)(`div`,{className:`empty-note`,children:[t,`没有可拆分的请求。`]});let n=Math.max(1,...e.map(e=>e.value)),r=e=>e?void 0:{fontFamily:`var(--font-body)`};return(0,j.jsx)(`div`,{className:`dist js-stagger js-grow`,children:e.map(e=>(0,j.jsxs)(`div`,{className:`d-row`,children:[e.tip?(0,j.jsx)(s,{content:e.tip,children:(0,j.jsx)(`span`,{className:`d-name`,style:r(e.mono),children:e.label})}):(0,j.jsx)(`span`,{className:`d-name`,style:r(e.mono),children:e.label}),(0,j.jsxs)(`span`,{className:`d-val`,children:[e.format===`credits`?f(e.value):l(e.value),` · `,e.trailing]}),(0,j.jsx)(`span`,{className:`d-track`,children:(0,j.jsx)(`i`,{style:{width:`${Math.max(2,Math.round(e.value/n*100))}%`}})})]},e.key))})}function F({items:e,windowLabel:t}){return e.length===0?(0,j.jsxs)(`div`,{className:`empty-note`,style:{padding:`8px 0`},children:[t,`没有按模型的消耗记录。`]}):(0,j.jsxs)(j.Fragment,{children:[(0,j.jsx)(`div`,{className:`tbl-scroll`,children:(0,j.jsxs)(`table`,{className:`tbl`,children:[(0,j.jsxs)(`caption`,{className:`sr-only`,children:[`按模型的 token 消耗明细,共 `,e.length,` 个模型`]}),(0,j.jsx)(`thead`,{children:(0,j.jsxs)(`tr`,{children:[(0,j.jsx)(`th`,{scope:`col`,children:`模型`}),(0,j.jsx)(`th`,{scope:`col`,className:`r`,children:`请求次数`}),(0,j.jsx)(`th`,{scope:`col`,className:`r`,children:`Token 消耗`}),(0,j.jsx)(`th`,{scope:`col`,className:`r`,children:`Token 占比`}),(0,j.jsx)(`th`,{scope:`col`,className:`r`,children:`消耗积分`}),(0,j.jsx)(`th`,{scope:`col`,className:`r`,children:`平均单次 Token`})]})}),(0,j.jsx)(`tbody`,{children:e.map(e=>{let t=e.displayName??e.model??`未知模型`;return(0,j.jsxs)(`tr`,{children:[(0,j.jsxs)(`td`,{className:`td-strong`,children:[t,e.tag?(0,j.jsx)(`span`,{className:`mu-tag`,children:e.tag}):null,e.multiplier==null?(0,j.jsx)(s,{content:`接口与本地快照都缺此模型倍率 —— 该行积分按中性倍率估算,不是上游真实计费`,children:(0,j.jsx)(`span`,{className:`mu-unknown`,children:`倍率未知`})}):null]}),(0,j.jsx)(`td`,{className:`r td-mono`,children:l(e.requests)}),(0,j.jsx)(`td`,{className:`r td-mono`,children:h(e.tokens??0)}),(0,j.jsx)(`td`,{className:`r td-mono`,children:o(e.share)}),(0,j.jsx)(`td`,{className:`r td-mono`,children:e.credits===null?(0,j.jsx)(s,{content:e.creditsUnknownCount?`本窗口 ${l(e.creditsUnknownCount)} 条请求上游均未回报单次费用(该上游只在账本给累计值)。真实消耗见上方「积分账本」。`:`上游未回报单次费用。真实消耗见上方「积分账本」。`,children:(0,j.jsx)(`span`,{className:`cred-unknown`,children:`--`})}):f(e.credits)}),(0,j.jsx)(`td`,{className:`r td-mono`,children:e.requests>0?h(Math.round((e.tokens??0)/e.requests)):`--`})]},e.model??t)})})]})}),(0,j.jsxs)(`div`,{className:`footer-note`,children:[`平均单次 = Token 消耗 ÷ 请求次数。接口不提供按模型的耗时,「较昨日」与「本计费周期」也无对应字段 —— 这三样一律留空而不是补一个看着合理的数。`,(0,j.jsx)(`br`,{}),`标着`,(0,j.jsx)(`b`,{children:`「倍率未知」`}),`的行,是 /v3/config 接口与本地快照都没有的模型:`,(0,j.jsx)(`b`,{children:`该行积分是按中性倍率估算的,不是上游真实计费`}),`。`]})]})}var I={ok:`额度接口正常`,quota_endpoint_not_configured:`未配置额度端点`,quota_endpoint_error:`额度端点拉取失败`};function L({quota:n,provenance:i,windowLabel:a}){let o=n.available&&n.remain!==null;return(0,j.jsxs)(g,{title:`配额数据来源`,aside:(0,j.jsx)(_,{tone:n.available?`live`:`amber`,dot:!0,children:I[n.reason]}),children:[(0,j.jsxs)(`div`,{className:`src-grid`,children:[(0,j.jsxs)(`div`,{className:`src-col`,children:[(0,j.jsxs)(`div`,{className:`src-head`,children:[(0,j.jsx)(t,{size:13,"aria-hidden":!0}),`来自上游额度接口`,(0,j.jsx)(`span`,{className:`tag tag-live`,children:`官方口径`})]}),(0,j.jsxs)(`ul`,{children:[(0,j.jsxs)(`li`,{children:[(0,j.jsx)(`b`,{children:`剩余积分`}),(0,j.jsx)(`i`,{children:`quota.remain`})]}),(0,j.jsxs)(`li`,{children:[(0,j.jsx)(`b`,{children:`总量`}),(0,j.jsx)(`i`,{children:`quota.total`})]}),(0,j.jsxs)(`li`,{children:[(0,j.jsx)(`b`,{children:`重置时间`}),(0,j.jsx)(`i`,{children:`quota.resetAt`})]})]}),(0,j.jsx)(`div`,{className:`src-state`,children:o?n.stale?(0,j.jsxs)(j.Fragment,{children:[(0,j.jsx)(r,{size:13,"aria-hidden":!0}),`上次拉取失败,当前显示的是上一次成功值(不会清空)。`]}):`已接入,随配额端点轮询刷新。`:(0,j.jsxs)(j.Fragment,{children:[`未接入 —— 上面三项显示 `,(0,j.jsx)(`i`,{children:`--`}),`。服务端不做估算,前端更不会替它编一个。`]})})]}),(0,j.jsxs)(`div`,{className:`src-col`,children:[(0,j.jsxs)(`div`,{className:`src-head`,children:[(0,j.jsx)(e,{size:13,"aria-hidden":!0}),`本机按请求累计`,(0,j.jsx)(`span`,{className:`tag tag-off`,children:`非官方口径`})]}),(0,j.jsxs)(`ul`,{children:[(0,j.jsxs)(`li`,{children:[(0,j.jsx)(`b`,{children:`已消耗积分`}),(0,j.jsx)(`i`,{children:`仅统计经本服务转发的请求,按上游实扣累加(官方客户端直连不计入)`})]}),(0,j.jsxs)(`li`,{children:[(0,j.jsxs)(`b`,{children:[a,`趋势`]}),(0,j.jsx)(`i`,{children:`本机日志按天聚合`})]}),(0,j.jsxs)(`li`,{children:[(0,j.jsx)(`b`,{children:`按模型 / 按提供商消耗`}),(0,j.jsx)(`i`,{children:`同一次聚合的一体两面`})]})]}),(0,j.jsx)(`div`,{className:`src-state`,children:`这些数即时产生,不等额度接口 —— 也正是它和「剩余积分」会对不齐的原因。`})]})]}),n.message?(0,j.jsx)(`div`,{className:`footer-note`,children:n.message}):null,(0,j.jsx)(`div`,{className:`footer-note`,children:i.note}),(0,j.jsxs)(`div`,{className:`footer-note`,children:[`官方额度接口按 `,(0,j.jsx)(`span`,{className:`code-chip`,children:`quota.pollSeconds`}),`(默认 `,(0,j.jsx)(`b`,{children:`30 秒`}),`)轮询, 所以「剩余积分」最多滞后 30 秒;本机累计的消耗是即时的。 两者最多相差 `,(0,j.jsx)(`b`,{children:`30 秒内的消耗量`}),` —— 这是取样时刻不同,不是账对不上。 来源标记:已消耗积分 `,(0,j.jsx)(`span`,{className:`code-chip`,children:i.creditsUsed}),` · `,`剩余积分 `,(0,j.jsx)(`span`,{className:`code-chip`,children:i.quotaRemain}),`。`]})]})}var R=`today`,z={today:null,"1h":null,"24h":null,"7d":7,"30d":30};function B(){let[e,t]=(0,A.useState)(()=>T()??R),n=u(()=>c.overview(e),[e],{cacheKey:`overview:${e}`});E(`usage-${e}-${n.data?`ready`:`pending`}`);let[r,i]=(0,A.useState)(`tokens`),s=n.data,p=z[e],I=s&&p?s.metrics.creditsUsed/p:null,B=s&&p?s.metrics.requests/p:null,V=s&&p?s.metrics.totalTokens/p:null,H=s?[...s.byModel].sort((e,t)=>(t.tokens??0)-(e.tokens??0)):[],U=s?[...s.byClient].sort((e,t)=>(t.tokens??0)-(e.tokens??0)):[],W=s&&s.quota.available&&s.quota.remain!==null&&I!==null&&I>0?Math.floor(s.quota.remain/I):null,G=s?s.quota.available?I===null||I<=0?`${a[s.window]}无消耗记录`:`按日均 ${f(I)} 积分估算`:`需要额度接口`:void 0,K=e=>{if(!s||s.byClient.length===0)return;let t=[...s.byClient].sort((t,n)=>(n[e]??0)-(t[e]??0));return(0,j.jsx)(k,{rows:t,metric:e,windowLabel:a[s.window],total:e===`credits`?s.metrics.creditsUsed:e===`tokens`?s.metrics.totalTokens:s.metrics.requests,totalCount:t.length})};return(0,j.jsxs)(`div`,{className:`view on`,children:[(0,j.jsx)(x,{title:`积分与用量`,status:s?(0,j.jsxs)(_,{tone:`live`,dot:!0,children:[a[s.window],` · `,m(s.generatedAt)]}):null,actions:(0,j.jsx)(S,{value:e,options:d,onChange:e=>{w(e),t(e)},width:148})}),(0,j.jsx)(`div`,{className:`view-body stack`,children:n.initial&&n.loading?(0,j.jsx)(C,{}):n.error?(0,j.jsx)(g,{children:(0,j.jsx)(v,{kind:`error`,title:`用量数据没取到`,detail:b(n.error),onRetry:n.reload})}):s?(0,j.jsxs)(j.Fragment,{children:[(0,j.jsx)(O,{metrics:s.metrics}),(0,j.jsx)(y,{items:[{label:`${a[s.window]}消耗`,value:f(s.metrics.creditsUsed),detail:`经本服务转发 · 上游实扣累计`,tip:K(`credits`),tipPos:`down`},{label:`${a[s.window]}请求`,value:l(s.metrics.requests),detail:`${l(s.metrics.activeClients)} 个密钥活跃`,tip:K(`requests`),tipPos:`down`},...I===null?[{label:`本窗口总 tokens`,value:h(s.metrics.totalTokens),detail:`输入 ${h(s.metrics.promptTokens)} · 输出 ${h(s.metrics.completionTokens)}`,tip:K(`tokens`),tipPos:`down`}]:[{label:`日均消耗`,value:f(I),detail:`${a[s.window]}消耗 ÷ ${p} 天`,tip:K(`credits`),tipPos:`down`},{label:`按当前速度可用天数`,value:W===null?`—`:l(W),detail:G,tone:s.quota.available?void 0:`amber`}]]}),(0,j.jsx)(g,{title:`${a[s.window]}趋势`,aside:(0,j.jsxs)(`span`,{className:`panel-aside-row`,children:[(0,j.jsx)(`span`,{className:`seg-tabs`,role:`group`,"aria-label":`趋势口径`,children:[`tokens`,`requests`].map(e=>(0,j.jsx)(`button`,{type:`button`,className:r===e?`on`:``,"aria-pressed":r===e,onClick:()=>i(e),children:e===`tokens`?`Token`:`请求数`},e))}),(0,j.jsxs)(_,{children:[`单位:`,M[r],` `,e===`1h`||e===`24h`||e===`today`?`/ 小时`:`/ 天`]})]}),padded:!1,children:(0,j.jsx)(`div`,{style:{padding:`0 20px 18px`},children:(0,j.jsx)(N,{points:s.trend,metric:r,avg:r===`tokens`?V:B})})}),(0,j.jsx)(g,{title:`按模型消耗明细`,aside:(0,j.jsx)(_,{children:`按 Token 排序`}),padded:!1,children:(0,j.jsx)(`div`,{style:{padding:`0 20px 18px`},children:(0,j.jsx)(F,{items:H,windowLabel:a[s.window]})})}),(0,j.jsxs)(g,{title:`按提供商消耗`,aside:(0,j.jsx)(_,{children:`按 Token 排序`}),children:[(0,j.jsx)(P,{windowLabel:a[s.window],items:U.map(e=>({key:e.clientId??`—`,label:e.client??`未识别`,value:e.tokens??0,format:`int`,trailing:`${o(e.share)} · ${f(e.credits)} 积分 · ${l(e.requests)} 次`,tip:(0,j.jsx)(D,{row:e})}))}),(0,j.jsx)(`div`,{className:`footer-note`,children:`「未识别」是正常的识别分支,不是错误 —— 没绑定密钥又没匹配到特征时归到这里。`})]}),(0,j.jsx)(L,{quota:s.quota,provenance:s.provenance,windowLabel:a[s.window]})]}):null})]})}export{B as UsagePage};
|