mirror of
https://github.com/foxhui/WebAI2API.git
synced 2026-06-16 21:03:59 +08:00
feat: 增加计数功能
This commit is contained in:
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{c as i,I as u}from"./index-CeQVA4cs.js";var l={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M928 140H96c-17.7 0-32 14.3-32 32v496c0 17.7 14.3 32 32 32h380v112H304c-8.8 0-16 7.2-16 16v48c0 4.4 3.6 8 8 8h432c4.4 0 8-3.6 8-8v-48c0-8.8-7.2-16-16-16H548V700h380c17.7 0 32-14.3 32-32V172c0-17.7-14.3-32-32-32zm-40 488H136V212h752v416z"}}]},name:"desktop",theme:"outlined"};function c(r){for(var t=1;t<arguments.length;t++){var e=arguments[t]!=null?Object(arguments[t]):{},n=Object.keys(e);typeof Object.getOwnPropertySymbols=="function"&&(n=n.concat(Object.getOwnPropertySymbols(e).filter(function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),n.forEach(function(a){s(r,a,e[a])})}return r}function s(r,t,e){return t in r?Object.defineProperty(r,t,{value:e,enumerable:!0,configurable:!0,writable:!0}):r[t]=e,r}var o=function(t,e){var n=c({},t,e.attrs);return i(u,c({},n,{icon:l}),null)};o.displayName="DesktopOutlined";o.inheritAttrs=!1;export{o as D};
|
||||
import{c as i,I as u}from"./index-BQYktfbJ.js";var l={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M928 140H96c-17.7 0-32 14.3-32 32v496c0 17.7 14.3 32 32 32h380v112H304c-8.8 0-16 7.2-16 16v48c0 4.4 3.6 8 8 8h432c4.4 0 8-3.6 8-8v-48c0-8.8-7.2-16-16-16H548V700h380c17.7 0 32-14.3 32-32V172c0-17.7-14.3-32-32-32zm-40 488H136V212h752v416z"}}]},name:"desktop",theme:"outlined"};function c(r){for(var t=1;t<arguments.length;t++){var e=arguments[t]!=null?Object(arguments[t]):{},n=Object.keys(e);typeof Object.getOwnPropertySymbols=="function"&&(n=n.concat(Object.getOwnPropertySymbols(e).filter(function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),n.forEach(function(a){s(r,a,e[a])})}return r}function s(r,t,e){return t in r?Object.defineProperty(r,t,{value:e,enumerable:!0,configurable:!0,writable:!0}):r[t]=e,r}var o=function(t,e){var n=c({},t,e.attrs);return i(u,c({},n,{icon:l}),null)};o.displayName="DesktopOutlined";o.inheritAttrs=!1;export{o as D};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
-1
@@ -1 +0,0 @@
|
||||
.log-container[data-v-6c3b8e99]{max-height:600px;overflow-y:auto;font-family:Consolas,Monaco,monospace;font-size:12px;background:#fafafa;border-radius:4px;padding:12px}.log-line[data-v-6c3b8e99]{padding:4px 0;border-bottom:1px solid #f0f0f0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.log-line[data-v-6c3b8e99]:hover{background:#e6f7ff;white-space:normal;word-break:break-all}.log-time[data-v-6c3b8e99]{color:#8c8c8c}.log-module[data-v-6c3b8e99]{color:#1890ff;margin-right:8px}.log-message[data-v-6c3b8e99]{color:#333}.level-erro .log-message[data-v-6c3b8e99]{color:#ff4d4f}.level-warn .log-message[data-v-6c3b8e99]{color:#faad14}.level-dbug .log-message[data-v-6c3b8e99]{color:#722ed1}.toolbar[data-v-6c3b8e99]{margin-bottom:16px}.toolbar-row[data-v-6c3b8e99]{display:flex;justify-content:space-between;align-items:center;gap:8px;margin-bottom:8px}.toolbar-row[data-v-6c3b8e99]:last-child{margin-bottom:0}@media(min-width:768px){.toolbar[data-v-6c3b8e99]{display:flex;justify-content:space-between;align-items:center;gap:12px}.toolbar-row[data-v-6c3b8e99]{margin-bottom:0}.toolbar-row[data-v-6c3b8e99]:last-child{flex:1;max-width:300px}}
|
||||
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
import{c as l,I as P,_ as q,j as J,r as p,l as Q,o as X,a as Y,b as N,d as b,w as o,g as v,f,h as m,u as C,R as k,y as Z,D as K,i as L,e as S,t as _,m as ee,F as te,s as R,M as ae,z as le,A as ne,B as oe}from"./index-CeQVA4cs.js";var se={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M304 280h56c4.4 0 8-3.6 8-8 0-28.3 5.9-53.2 17.1-73.5 10.6-19.4 26-34.8 45.4-45.4C450.9 142 475.7 136 504 136h16c28.3 0 53.2 5.9 73.5 17.1 19.4 10.6 34.8 26 45.4 45.4C650 218.9 656 243.7 656 272c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8 0-40-8.8-76.7-25.9-108.1a184.31 184.31 0 00-74-74C596.7 72.8 560 64 520 64h-16c-40 0-76.7 8.8-108.1 25.9a184.31 184.31 0 00-74 74C304.8 195.3 296 232 296 272c0 4.4 3.6 8 8 8z"}},{tag:"path",attrs:{d:"M940 512H792V412c76.8 0 139-62.2 139-139 0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8a63 63 0 01-63 63H232a63 63 0 01-63-63c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8 0 76.8 62.2 139 139 139v100H84c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h148v96c0 6.5.2 13 .7 19.3C164.1 728.6 116 796.7 116 876c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8 0-44.2 23.9-82.9 59.6-103.7a273 273 0 0022.7 49c24.3 41.5 59 76.2 100.5 100.5S460.5 960 512 960s99.8-13.9 141.3-38.2a281.38 281.38 0 00123.2-149.5A120 120 0 01836 876c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8 0-79.3-48.1-147.4-116.7-176.7.4-6.4.7-12.8.7-19.3v-96h148c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM716 680c0 36.8-9.7 72-27.8 102.9-17.7 30.3-43 55.6-73.3 73.3C584 874.3 548.8 884 512 884s-72-9.7-102.9-27.8c-30.3-17.7-55.6-43-73.3-73.3A202.75 202.75 0 01308 680V412h408v268z"}}]},name:"bug",theme:"outlined"};function D(n){for(var t=1;t<arguments.length;t++){var a=arguments[t]!=null?Object(arguments[t]):{},s=Object.keys(a);typeof Object.getOwnPropertySymbols=="function"&&(s=s.concat(Object.getOwnPropertySymbols(a).filter(function(c){return Object.getOwnPropertyDescriptor(a,c).enumerable}))),s.forEach(function(c){re(n,c,a[c])})}return n}function re(n,t,a){return t in n?Object.defineProperty(n,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):n[t]=a,n}var j=function(t,a){var s=D({},t,a.attrs);return l(P,D({},s,{icon:se}),null)};j.displayName="BugOutlined";j.inheritAttrs=!1;var ce={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M464 720a48 48 0 1096 0 48 48 0 10-96 0zm16-304v184c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V416c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8zm475.7 440l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48zm-783.5-27.9L512 239.9l339.8 588.2H172.2z"}}]},name:"warning",theme:"outlined"};function E(n){for(var t=1;t<arguments.length;t++){var a=arguments[t]!=null?Object(arguments[t]):{},s=Object.keys(a);typeof Object.getOwnPropertySymbols=="function"&&(s=s.concat(Object.getOwnPropertySymbols(a).filter(function(c){return Object.getOwnPropertyDescriptor(a,c).enumerable}))),s.forEach(function(c){ie(n,c,a[c])})}return n}function ie(n,t,a){return t in n?Object.defineProperty(n,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):n[t]=a,n}var I=function(t,a){var s=E({},t,a.attrs);return l(P,E({},s,{icon:ce}),null)};I.displayName="WarningOutlined";I.inheritAttrs=!1;const ue={class:"toolbar"},de={class:"toolbar-row"},fe={class:"toolbar-row"},ve={style:{"margin-bottom":"12px",color:"#8c8c8c","font-size":"12px"}},me={key:0,style:{color:"#1890ff","margin-left":"8px"}},pe={class:"log-container"},ge={class:"log-time"},_e={class:"log-module"},he={class:"log-message"},Oe={__name:"logs",setup(n){const t=J(),a=p([]),s=p(!1),c=p(0),h=p(!1),g=p(null),y=p(""),w=p("all"),U={INFO:{color:"#1890ff",icon:oe},WARN:{color:"#faad14",icon:I},ERRO:{color:"#ff4d4f",icon:ne},DBUG:{color:"#722ed1",icon:j}},z=async()=>{s.value=!0;try{const r=await fetch("/admin/logs?lines=500",{headers:t.getHeaders()});if(r.ok){const e=await r.json();a.value=A(e.logs||[]),c.value=e.total||0}}catch{R.error("获取日志失败")}finally{s.value=!1}},A=r=>r.map((e,i)=>{const d=e.match(/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}) \[(\w+)\] \[([^\]]+)\] (.*)$/);return d?{id:i,time:d[1],level:d[2],module:d[3],message:d[4],raw:e}:{id:i,raw:e,level:"INFO",time:"",module:"",message:e}}),x=Q(()=>a.value.filter(e=>{if(w.value!=="all"&&e.level!==w.value)return!1;if(y.value){const i=y.value.toLowerCase();return e.raw.toLowerCase().includes(i)}return!0}).reverse()),F=()=>{ae.confirm({title:"确认清除日志",content:"此操作将删除所有系统日志文件,是否继续?",okText:"确认清除",okType:"danger",cancelText:"取消",async onOk(){try{(await fetch("/admin/logs",{method:"DELETE",headers:t.getHeaders()})).ok?(R.success("日志已清除"),a.value=[],c.value=0):R.error("清除失败")}catch{R.error("请求失败")}}})},M=()=>{const r=a.value.map(O=>O.raw).join(`
|
||||
`),e=new Blob([r],{type:"text/plain"}),i=URL.createObjectURL(e),d=document.createElement("a");d.href=i,d.download=`system-${new Date().toISOString().split("T")[0]}.log`,d.click(),URL.revokeObjectURL(i)},T=r=>{h.value=r,r?(z(),g.value=setInterval(z,5e3)):g.value&&(clearInterval(g.value),g.value=null)};return X(()=>{z()}),Y(()=>{g.value&&clearInterval(g.value)}),(r,e)=>{const i=f("a-select-option"),d=f("a-select"),O=f("a-button"),B=f("a-tooltip"),V=f("a-space"),W=f("a-input-search"),$=f("a-tag"),H=f("a-empty"),G=f("a-card");return b(),N(G,{title:"系统日志",bordered:!1},{default:o(()=>[v("div",ue,[v("div",de,[l(d,{value:w.value,"onUpdate:value":e[0]||(e[0]=u=>w.value=u),style:{width:"90px"},size:"small"},{default:o(()=>[l(i,{value:"all"},{default:o(()=>[...e[3]||(e[3]=[m("全部",-1)])]),_:1}),l(i,{value:"INFO"},{default:o(()=>[...e[4]||(e[4]=[m("INFO",-1)])]),_:1}),l(i,{value:"WARN"},{default:o(()=>[...e[5]||(e[5]=[m("WARN",-1)])]),_:1}),l(i,{value:"ERRO"},{default:o(()=>[...e[6]||(e[6]=[m("ERROR",-1)])]),_:1}),l(i,{value:"DBUG"},{default:o(()=>[...e[7]||(e[7]=[m("DEBUG",-1)])]),_:1})]),_:1},8,["value"]),l(V,{size:4},{default:o(()=>[l(B,{title:h.value?"关闭自动刷新":"开启自动刷新"},{default:o(()=>[l(O,{size:"small",type:h.value?"primary":"default",onClick:e[1]||(e[1]=u=>T(!h.value))},{icon:o(()=>[l(C(k))]),_:1},8,["type"])]),_:1},8,["title"]),l(B,{title:"导出日志"},{default:o(()=>[l(O,{size:"small",onClick:M},{icon:o(()=>[l(C(Z))]),_:1})]),_:1}),l(B,{title:"清除日志"},{default:o(()=>[l(O,{size:"small",danger:"",onClick:F},{icon:o(()=>[l(C(K))]),_:1})]),_:1})]),_:1})]),v("div",fe,[l(W,{value:y.value,"onUpdate:value":e[2]||(e[2]=u=>y.value=u),placeholder:"搜索日志",size:"small","enter-button":"","allow-clear":"",style:{width:"100%"}},null,8,["value"])])]),v("div",ve,[m(" 共 "+_(c.value)+" 条日志,当前显示 "+_(x.value.length)+" 条 ",1),h.value?(b(),L("span",me,[l(C(k),{spin:!0}),e[8]||(e[8]=m(" 自动刷新中 ",-1))])):S("",!0)]),v("div",pe,[(b(!0),L(te,null,ee(x.value,u=>(b(),L("div",{key:u.id,class:le(["log-line","level-"+u.level.toLowerCase()])},[v("span",ge,_(u.time),1),l($,{color:U[u.level]?.color||"#8c8c8c",size:"small",style:{margin:"0 8px"}},{default:o(()=>[m(_(u.level),1)]),_:2},1032,["color"]),v("span",_e,"["+_(u.module)+"]",1),v("span",he,_(u.message),1)],2))),128)),x.value.length===0?(b(),N(H,{key:0,description:"暂无日志"})):S("",!0)])]),_:1})}}},ye=q(Oe,[["__scopeId","data-v-6c3b8e99"]]);export{ye as default};
|
||||
Vendored
+2
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -0,0 +1 @@
|
||||
.log-container[data-v-f89c259b]{max-height:600px;overflow-y:auto;font-family:Consolas,Monaco,monospace;font-size:12px;background:#fafafa;border-radius:4px;padding:12px}.log-line[data-v-f89c259b]{padding:4px 0;border-bottom:1px solid #f0f0f0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.log-line[data-v-f89c259b]:hover{background:#e6f7ff;white-space:normal;word-break:break-all}.log-time[data-v-f89c259b]{color:#8c8c8c}.log-module[data-v-f89c259b]{color:#1890ff;margin-right:8px}.log-message[data-v-f89c259b]{color:#333}.level-erro .log-message[data-v-f89c259b]{color:#ff4d4f}.level-warn .log-message[data-v-f89c259b]{color:#faad14}.level-dbug .log-message[data-v-f89c259b]{color:#722ed1}.toolbar[data-v-f89c259b]{margin-bottom:16px}.toolbar-row[data-v-f89c259b]{display:flex;justify-content:space-between;align-items:center;gap:8px;margin-bottom:8px}.toolbar-row[data-v-f89c259b]:last-child{margin-bottom:0}@media(min-width:768px){.toolbar[data-v-f89c259b]{display:flex;justify-content:space-between;align-items:center;gap:12px}.toolbar-row[data-v-f89c259b]{margin-bottom:0}.toolbar-row[data-v-f89c259b]:last-child{flex:1;max-width:300px}}.stats-content[data-v-f89c259b]{display:flex;align-items:center;flex-wrap:wrap;gap:8px}.stats-numbers[data-v-f89c259b]{display:flex;align-items:center;gap:20px}.stat-item[data-v-f89c259b]{display:flex;align-items:center;gap:6px;padding:4px 12px;background:#fafafa;border-radius:6px;transition:all .2s}.stat-item[data-v-f89c259b]:hover{background:#f0f0f0}.stat-item.success[data-v-f89c259b]{color:#52c41a}.stat-item.error[data-v-f89c259b]{color:#ff4d4f}.stat-item.neutral[data-v-f89c259b]{color:#8c8c8c}.stat-value[data-v-f89c259b]{font-size:18px;font-weight:600;font-family:SF Mono,Monaco,monospace}.stat-label[data-v-f89c259b]{font-size:12px;color:#8c8c8c}@media(max-width:576px){.stats-content[data-v-f89c259b]{flex-direction:column;align-items:flex-start}.stats-content .ant-divider[data-v-f89c259b]{display:none}.stats-numbers[data-v-f89c259b]{margin-top:8px}}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
import{_ as b,k as w,l as k,o as c,b as C,d as S,w as n,c as o,g as e,f as a,h as i}from"./index-BQYktfbJ.js";const B={style:{"margin-bottom":"8px"}},T={style:{"margin-bottom":"8px"}},z={style:{"margin-bottom":"8px"}},U={style:{display:"flex","justify-content":"flex-end","margin-top":"24px"}},M={style:{"margin-bottom":"8px"}},j={style:{"margin-bottom":"8px"}},q={style:{display:"flex","justify-content":"flex-end","margin-top":"24px"}},L={__name:"server",setup(N){const d=w(),s=k({port:5173,authToken:"",keepaliveMode:"comment",queueBuffer:2,imageLimit:5});c(async()=>{await d.fetchServerConfig(),Object.assign(s,d.serverConfig)});const m=async()=>{await d.saveServerConfig(s)};return(V,t)=>{const p=a("a-input-number"),r=a("a-col"),y=a("a-input-password"),u=a("a-select-option"),g=a("a-select"),f=a("a-row"),v=a("a-button"),x=a("a-card"),_=a("a-layout");return S(),C(_,{style:{background:"transparent"}},{default:n(()=>[o(x,{title:"服务器设置",bordered:!1,style:{width:"100%"}},{default:n(()=>[o(f,{gutter:[16,16]},{default:n(()=>[o(r,{xs:24,md:12},{default:n(()=>[e("div",B,[t[5]||(t[5]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"监听端口",-1)),t[6]||(t[6]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}}," 设置服务器监听的端口号,默认为 5173 ",-1)),o(p,{value:s.port,"onUpdate:value":t[0]||(t[0]=l=>s.port=l),min:1,max:65535,placeholder:"请输入端口号",style:{width:"100%"}},null,8,["value"])])]),_:1}),o(r,{xs:24,md:12},{default:n(()=>[e("div",T,[t[7]||(t[7]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"鉴权 Token",-1)),t[8]||(t[8]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}}," 用于 API 请求鉴权的密钥,留空则不启用鉴权 ",-1)),o(y,{value:s.authToken,"onUpdate:value":t[1]||(t[1]=l=>s.authToken=l),placeholder:"请输入 Token",type:"password"},null,8,["value"])])]),_:1}),o(r,{xs:24,md:12},{default:n(()=>[e("div",z,[t[11]||(t[11]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"心跳包类型",-1)),t[12]||(t[12]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}}," 选择 SSE 流式响应的心跳包格式 ",-1)),o(g,{value:s.keepaliveMode,"onUpdate:value":t[2]||(t[2]=l=>s.keepaliveMode=l),style:{width:"100%"},placeholder:"请选择心跳包类型"},{default:n(()=>[o(u,{value:"comment"},{default:n(()=>[...t[9]||(t[9]=[i("Comment - 注释格式",-1)])]),_:1}),o(u,{value:"content"},{default:n(()=>[...t[10]||(t[10]=[i("Content - 内容格式",-1)])]),_:1})]),_:1},8,["value"])])]),_:1})]),_:1}),e("div",U,[o(v,{type:"primary",onClick:m},{default:n(()=>[...t[13]||(t[13]=[i(" 保存设置 ",-1)])]),_:1})])]),_:1}),o(x,{title:"队列设置",bordered:!1,style:{width:"100%","margin-top":"10px"}},{default:n(()=>[o(f,{gutter:[16,16]},{default:n(()=>[o(r,{xs:24,md:12},{default:n(()=>[e("div",M,[t[14]||(t[14]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"队列缓冲区大小",-1)),t[15]||(t[15]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}},[i(" 非流式请求的额外排队数(设为 0 则不限制非流式请求数量)"),e("br"),i(" 实际队列上限 = Workers数量 + 缓冲区大小 ")],-1)),o(p,{value:s.queueBuffer,"onUpdate:value":t[3]||(t[3]=l=>s.queueBuffer=l),min:0,max:100,placeholder:"默认为 2",style:{width:"100%"}},null,8,["value"])])]),_:1}),o(r,{xs:24,md:12},{default:n(()=>[e("div",j,[t[16]||(t[16]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"图片数量上限",-1)),t[17]||(t[17]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}},[i(" 单次请求最多支持的图片附件数量"),e("br"),i(" 网页最多支持10个附件,超出会被丢弃 ")],-1)),o(p,{value:s.imageLimit,"onUpdate:value":t[4]||(t[4]=l=>s.imageLimit=l),min:1,max:10,placeholder:"默认为 5",style:{width:"100%"}},null,8,["value"])])]),_:1})]),_:1}),e("div",q,[o(v,{type:"primary",onClick:m},{default:n(()=>[...t[18]||(t[18]=[i(" 保存设置 ",-1)])]),_:1})])]),_:1})]),_:1})}}},A=b(L,[["__scopeId","data-v-bd32923f"]]);export{A as default};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
import{_ as b,j as w,k,o as c,b as C,d as S,w as n,c as o,g as e,f as a,h as i}from"./index-CeQVA4cs.js";const B={style:{"margin-bottom":"8px"}},T={style:{"margin-bottom":"8px"}},z={style:{"margin-bottom":"8px"}},U={style:{display:"flex","justify-content":"flex-end","margin-top":"24px"}},j={style:{"margin-bottom":"8px"}},M={style:{"margin-bottom":"8px"}},q={style:{display:"flex","justify-content":"flex-end","margin-top":"24px"}},L={__name:"server",setup(N){const d=w(),s=k({port:5173,authToken:"",keepaliveMode:"comment",queueBuffer:2,imageLimit:5});c(async()=>{await d.fetchServerConfig(),Object.assign(s,d.serverConfig)});const m=async()=>{await d.saveServerConfig(s)};return(V,t)=>{const p=a("a-input-number"),r=a("a-col"),y=a("a-input-password"),u=a("a-select-option"),g=a("a-select"),f=a("a-row"),v=a("a-button"),x=a("a-card"),_=a("a-layout");return S(),C(_,{style:{background:"transparent"}},{default:n(()=>[o(x,{title:"服务器设置",bordered:!1,style:{width:"100%"}},{default:n(()=>[o(f,{gutter:[16,16]},{default:n(()=>[o(r,{xs:24,md:12},{default:n(()=>[e("div",B,[t[5]||(t[5]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"监听端口",-1)),t[6]||(t[6]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}}," 设置服务器监听的端口号,默认为 5173 ",-1)),o(p,{value:s.port,"onUpdate:value":t[0]||(t[0]=l=>s.port=l),min:1,max:65535,placeholder:"请输入端口号",style:{width:"100%"}},null,8,["value"])])]),_:1}),o(r,{xs:24,md:12},{default:n(()=>[e("div",T,[t[7]||(t[7]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"鉴权 Token",-1)),t[8]||(t[8]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}}," 用于 API 请求鉴权的密钥,留空则不启用鉴权 ",-1)),o(y,{value:s.authToken,"onUpdate:value":t[1]||(t[1]=l=>s.authToken=l),placeholder:"请输入 Token",type:"password"},null,8,["value"])])]),_:1}),o(r,{xs:24,md:12},{default:n(()=>[e("div",z,[t[11]||(t[11]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"心跳包类型",-1)),t[12]||(t[12]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}}," 选择 SSE 流式响应的心跳包格式 ",-1)),o(g,{value:s.keepaliveMode,"onUpdate:value":t[2]||(t[2]=l=>s.keepaliveMode=l),style:{width:"100%"},placeholder:"请选择心跳包类型"},{default:n(()=>[o(u,{value:"comment"},{default:n(()=>[...t[9]||(t[9]=[i("Comment - 注释格式",-1)])]),_:1}),o(u,{value:"content"},{default:n(()=>[...t[10]||(t[10]=[i("Content - 内容格式",-1)])]),_:1})]),_:1},8,["value"])])]),_:1})]),_:1}),e("div",U,[o(v,{type:"primary",onClick:m},{default:n(()=>[...t[13]||(t[13]=[i(" 保存设置 ",-1)])]),_:1})])]),_:1}),o(x,{title:"队列设置",bordered:!1,style:{width:"100%","margin-top":"10px"}},{default:n(()=>[o(f,{gutter:[16,16]},{default:n(()=>[o(r,{xs:24,md:12},{default:n(()=>[e("div",j,[t[14]||(t[14]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"队列缓冲区大小",-1)),t[15]||(t[15]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}},[i(" 非流式请求的额外排队数(设为 0 则不限制非流式请求数量)"),e("br"),i(" 实际队列上限 = Workers数量 + 缓冲区大小 ")],-1)),o(p,{value:s.queueBuffer,"onUpdate:value":t[3]||(t[3]=l=>s.queueBuffer=l),min:0,max:100,placeholder:"默认为 2",style:{width:"100%"}},null,8,["value"])])]),_:1}),o(r,{xs:24,md:12},{default:n(()=>[e("div",M,[t[16]||(t[16]=e("div",{style:{"font-weight":"600","margin-bottom":"4px"}},"图片数量上限",-1)),t[17]||(t[17]=e("div",{style:{"font-size":"12px",color:"#8c8c8c","margin-bottom":"8px"}},[i(" 单次请求最多支持的图片附件数量"),e("br"),i(" 网页最多支持10个附件,超出会被丢弃 ")],-1)),o(p,{value:s.imageLimit,"onUpdate:value":t[4]||(t[4]=l=>s.imageLimit=l),min:1,max:10,placeholder:"默认为 5",style:{width:"100%"}},null,8,["value"])])]),_:1})]),_:1}),e("div",q,[o(v,{type:"primary",onClick:m},{default:n(()=>[...t[18]||(t[18]=[i(" 保存设置 ",-1)])]),_:1})])]),_:1})]),_:1})}}},A=b(L,[["__scopeId","data-v-bd32923f"]]);export{A as default};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
import{x as i,j as a,s as r}from"./index-CeQVA4cs.js";const u=i("system",{state:()=>({status:"",version:"1.0.0",systemVersion:"",uptime:0,cpuUsage:0,memoryUsage:{total:0,used:0,free:0},safeMode:{enabled:!1,reason:null},stats:{totalRequests:0,successRate:0,activeWorkers:0,totalWorkers:0,avgResponseTime:0}}),actions:{async fetchStatus(){const t=a();try{const e=await fetch("/admin/status",{headers:t.getHeaders()});if(e.ok){const s=await e.json();this.$patch(s)}}catch(e){console.error("Failed to fetch system status:",e)}},async fetchStats(){const t=a();try{const e=await fetch("/admin/stats",{headers:t.getHeaders()});if(e.ok){const s=await e.json();this.stats=s}}catch(e){console.error("Failed to fetch stats:",e)}},async restartService(t={}){const e=a(),{loginMode:s,workerName:n}=t;try{const o=await(await fetch("/admin/restart",{method:"POST",headers:{...e.getHeaders(),"Content-Type":"application/json"},body:JSON.stringify({loginMode:s,workerName:n})})).json();return o.success?(r.success(o.message||"服务重启中..."),!0):(r.error("重启失败"),!1)}catch{return r.error("重启请求失败"),!1}},async stopService(){const t=a();try{const s=await(await fetch("/admin/stop",{method:"POST",headers:t.getHeaders()})).json();return s.success?(r.success(s.message||"服务停止中..."),!0):(r.error("停止失败"),!1)}catch{return r.error("停止请求失败"),!1}}}});export{u};
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
import{y as i,k as a,v as r}from"./index-BQYktfbJ.js";const u=i("system",{state:()=>({status:"",version:"1.0.0",systemVersion:"",uptime:0,cpuUsage:0,memoryUsage:{total:0,used:0,free:0},safeMode:{enabled:!1,reason:null},stats:{totalRequests:0,successRate:0,activeWorkers:0,totalWorkers:0,avgResponseTime:0,success:0,failed:0}}),actions:{async fetchStatus(){const t=a();try{const e=await fetch("/admin/status",{headers:t.getHeaders()});if(e.ok){const s=await e.json();this.$patch(s)}}catch(e){console.error("Failed to fetch system status:",e)}},async fetchStats(){const t=a();try{const e=await fetch("/admin/stats",{headers:t.getHeaders()});if(e.ok){const s=await e.json();this.stats=s}}catch(e){console.error("Failed to fetch stats:",e)}},async restartService(t={}){const e=a(),{loginMode:s,workerName:n}=t;try{const o=await(await fetch("/admin/restart",{method:"POST",headers:{...e.getHeaders(),"Content-Type":"application/json"},body:JSON.stringify({loginMode:s,workerName:n})})).json();return o.success?(r.success(o.message||"服务重启中..."),!0):(r.error("重启失败"),!1)}catch{return r.error("重启请求失败"),!1}},async stopService(){const t=a();try{const s=await(await fetch("/admin/stop",{method:"POST",headers:t.getHeaders()})).json();return s.success?(r.success(s.message||"服务停止中..."),!0):(r.error("停止失败"),!1)}catch{return r.error("停止请求失败"),!1}}}});export{u};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -6,7 +6,7 @@
|
||||
<link rel="icon" type="image/png" href="/favicon.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>WebAI2API</title>
|
||||
<script type="module" crossorigin src="/assets/index-CeQVA4cs.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-BQYktfbJ.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-BVr8U7Bl.css">
|
||||
</head>
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ import {
|
||||
LineChartOutlined,
|
||||
SyncOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
CheckCircleOutlined
|
||||
CheckCircleOutlined,
|
||||
CloseCircleOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
|
||||
const systemStore = useSystemStore();
|
||||
@@ -205,6 +206,22 @@ onUnmounted(() => {
|
||||
</a-statistic>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="16" style="margin-top: 16px">
|
||||
<a-col :span="12">
|
||||
<a-statistic title="今日成功" :value="systemStore.stats.success || 0">
|
||||
<template #prefix>
|
||||
<CheckCircleOutlined style="color: #52c41a" />
|
||||
</template>
|
||||
</a-statistic>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-statistic title="今日失败" :value="systemStore.stats.failed || 0">
|
||||
<template #prefix>
|
||||
<CloseCircleOutlined style="color: #ff4d4f" />
|
||||
</template>
|
||||
</a-statistic>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
@@ -9,7 +9,8 @@ import {
|
||||
WarningOutlined,
|
||||
CloseCircleOutlined,
|
||||
InfoCircleOutlined,
|
||||
BugOutlined
|
||||
BugOutlined,
|
||||
CheckCircleOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
|
||||
@@ -23,6 +24,11 @@ const refreshInterval = ref(null);
|
||||
const searchText = ref('');
|
||||
const levelFilter = ref('all');
|
||||
|
||||
// 统计查询相关
|
||||
const dateRange = ref([]);
|
||||
const rangeStats = ref({ success: 0, failed: 0, days: 0 });
|
||||
const statsLoading = ref(false);
|
||||
|
||||
// 日志级别配置
|
||||
const levelConfig = {
|
||||
'INFO': { color: '#1890ff', icon: InfoCircleOutlined },
|
||||
@@ -141,6 +147,61 @@ const toggleAutoRefresh = (newState) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 查询日期范围统计
|
||||
const fetchRangeStats = async () => {
|
||||
if (!dateRange.value || dateRange.value.length !== 2) {
|
||||
rangeStats.value = { success: 0, failed: 0, days: 0 };
|
||||
return;
|
||||
}
|
||||
|
||||
statsLoading.value = true;
|
||||
try {
|
||||
const [start, end] = dateRange.value;
|
||||
const res = await fetch(
|
||||
`/admin/stats/range?start=${start.format('YYYY-MM-DD')}&end=${end.format('YYYY-MM-DD')}`,
|
||||
{ headers: settingsStore.getHeaders() }
|
||||
);
|
||||
if (res.ok) {
|
||||
rangeStats.value = await res.json();
|
||||
}
|
||||
} catch (e) {
|
||||
message.error('获取统计失败');
|
||||
} finally {
|
||||
statsLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 删除选定范围的统计数据
|
||||
const clearRangeStats = () => {
|
||||
if (!dateRange.value || dateRange.value.length !== 2) {
|
||||
message.warning('请先选择日期范围');
|
||||
return;
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: `确定要删除 ${dateRange.value[0].format('YYYY-MM-DD')} 至 ${dateRange.value[1].format('YYYY-MM-DD')} 的统计数据吗?`,
|
||||
okText: '删除',
|
||||
okType: 'danger',
|
||||
cancelText: '取消',
|
||||
async onOk() {
|
||||
try {
|
||||
const [start, end] = dateRange.value;
|
||||
const res = await fetch(
|
||||
`/admin/stats/range?start=${start.format('YYYY-MM-DD')}&end=${end.format('YYYY-MM-DD')}`,
|
||||
{ method: 'DELETE', headers: settingsStore.getHeaders() }
|
||||
);
|
||||
if (res.ok) {
|
||||
message.success('统计数据已删除');
|
||||
rangeStats.value = { success: 0, failed: 0, days: 0 };
|
||||
}
|
||||
} catch (e) {
|
||||
message.error('删除失败');
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchLogs();
|
||||
});
|
||||
@@ -153,7 +214,47 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-card title="系统日志" :bordered="false">
|
||||
<!-- 统计查询面板 -->
|
||||
<a-card title="请求统计" :bordered="false">
|
||||
<template #extra>
|
||||
<a-button type="link" danger size="small" @click="clearRangeStats"
|
||||
:disabled="!dateRange || dateRange.length !== 2">
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
删除统计
|
||||
</a-button>
|
||||
</template>
|
||||
|
||||
<div class="stats-content">
|
||||
<a-range-picker v-model:value="dateRange" :format="'YYYY-MM-DD'" :placeholder="['开始日期', '结束日期']"
|
||||
size="small" style="width: 240px" @change="fetchRangeStats" />
|
||||
|
||||
<a-divider type="vertical" style="height: 32px; margin: 0 16px" />
|
||||
|
||||
<a-spin :spinning="statsLoading" size="small">
|
||||
<div class="stats-numbers">
|
||||
<div class="stat-item success">
|
||||
<CheckCircleOutlined />
|
||||
<span class="stat-value">{{ rangeStats.success }}</span>
|
||||
<span class="stat-label">成功</span>
|
||||
</div>
|
||||
<div class="stat-item error">
|
||||
<CloseCircleOutlined />
|
||||
<span class="stat-value">{{ rangeStats.failed }}</span>
|
||||
<span class="stat-label">失败</span>
|
||||
</div>
|
||||
<div class="stat-item neutral">
|
||||
<span class="stat-value">{{ rangeStats.days }}</span>
|
||||
<span class="stat-label">天</span>
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
</div>
|
||||
</a-card>
|
||||
|
||||
<!-- 系统日志 -->
|
||||
<a-card title="系统日志" :bordered="false" style="margin-top: 24px">
|
||||
<!-- 工具栏 -->
|
||||
<div class="toolbar">
|
||||
<!-- 第一行:级别筛选和操作按钮 -->
|
||||
@@ -305,4 +406,72 @@ onUnmounted(() => {
|
||||
max-width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 统计内容样式 */
|
||||
|
||||
.stats-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.stats-numbers {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 4px 12px;
|
||||
background: #fafafa;
|
||||
border-radius: 6px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.stat-item:hover {
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.stat-item.success {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.stat-item.error {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.stat-item.neutral {
|
||||
color: #8c8c8c;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
font-family: 'SF Mono', 'Monaco', monospace;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 12px;
|
||||
color: #8c8c8c;
|
||||
}
|
||||
|
||||
/* 响应式:小屏幕统计面板垂直布局 */
|
||||
@media (max-width: 576px) {
|
||||
.stats-content {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.stats-content .ant-divider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.stats-numbers {
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -28,7 +28,9 @@ export const useSystemStore = defineStore('system', {
|
||||
successRate: 0,
|
||||
activeWorkers: 0,
|
||||
totalWorkers: 0,
|
||||
avgResponseTime: 0
|
||||
avgResponseTime: 0,
|
||||
success: 0,
|
||||
failed: 0
|
||||
}
|
||||
}),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user