llonebot-dist 7.1.1 → 7.1.2
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/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"llonebot-dist","version":"7.1.
|
|
1
|
+
{"name":"llonebot-dist","version":"7.1.2","type":"module","description":"","main":"llonebot.js","author":"linyuchen"}
|
|
@@ -287,7 +287,7 @@ Error generating stack: `+s.message+`
|
|
|
287
287
|
before:content-[''] before:absolute before:top-0.5 before:left-0.5\r
|
|
288
288
|
before:w-5 before:h-5 before:rounded-full before:bg-white\r
|
|
289
289
|
before:transition-transform before:duration-200\r
|
|
290
|
-
checked:before:translate-x-6`})]}),e.autoDeleteFile&&o.jsx("div",{className:"pl-4",children:o.jsxs("label",{className:"block",children:[o.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[o.jsx(Br,{size:16,className:"text-gray-600"}),o.jsx("span",{className:"text-sm font-medium text-gray-700",children:"自动删除时间(秒)"})]}),o.jsx("input",{type:"number",value:e.autoDeleteFileSecond,onChange:l=>r("autoDeleteFileSecond",parseInt(l.target.value)),min:"1",max:"3600",className:"input-field",placeholder:"60"}),o.jsx("p",{className:"text-xs text-gray-500 mt-1",children:"文件接收后多少秒自动删除(1-3600秒)"})]})})]})]}),o.jsxs("div",{className:"card p-6",children:[o.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[o.jsx("div",{className:"w-10 h-10 rounded-xl bg-gradient-to-br from-purple-500 to-pink-600 flex items-center justify-center",children:o.jsx(Br,{size:20,className:"text-white"})}),o.jsxs("div",{children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"缓存设置"}),o.jsx("p",{className:"text-sm text-gray-600",children:"消息缓存相关配置"})]})]}),o.jsxs("label",{className:"block",children:[o.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[o.jsx(Br,{size:16,className:"text-purple-600"}),o.jsx("span",{className:"text-sm font-medium text-gray-700",children:"消息缓存过期时间(秒)"})]}),o.jsx("input",{type:"number",value:e.msgCacheExpire,onChange:l=>r("msgCacheExpire",parseInt(l.target.value)),min:"1",max:"86400",className:"input-field",placeholder:"3600"}),o.jsx("p",{className:"text-xs text-gray-500 mt-1",children:"消息在缓存中保留的时间(1-86400秒)"})]})]}),o.jsxs("div",{className:"card p-6",children:[o.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[o.jsx("div",{className:"w-10 h-10 rounded-xl bg-gradient-to-br from-green-500 to-teal-600 flex items-center justify-center",children:o.jsx(da,{size:20,className:"text-white"})}),o.jsxs("div",{children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"扩展功能"}),o.jsx("p",{className:"text-sm text-gray-600",children:"第三方服务配置"})]})]}),o.jsxs("label",{className:"block",children:[o.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[o.jsx(da,{size:16,className:"text-green-600"}),o.jsx("span",{className:"text-sm font-medium text-gray-700",children:"音乐签名地址"})]}),o.jsx("input",{type:"text",value:e.musicSignUrl,onChange:l=>r("musicSignUrl",l.target.value),placeholder:"https://example.com/sign",className:"input-field"}),o.jsx("p",{className:"text-xs text-gray-500 mt-1",children:"用于音乐卡片签名的服务地址"})]})]}),o.jsxs("div",{className:"card p-6",children:[o.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[o.jsx("div",{className:"w-10 h-10 rounded-xl bg-gradient-to-br from-red-500 to-pink-600 flex items-center justify-center",children:o.jsx(zp,{size:20,className:"text-white"})}),o.jsxs("div",{children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"安全设置"}),o.jsx("p",{className:"text-sm text-gray-600",children:"WebUI 访问控制"})]})]}),o.jsxs("div",{className:"flex items-center justify-between p-4 bg-gray-50/50 rounded-xl hover:bg-gray-100/50 transition-colors",children:[o.jsxs("div",{className:"flex items-center gap-3",children:[o.jsx(Mc,{size:20,className:"text-red-600"}),o.jsxs("div",{children:[o.jsx("div",{className:"text-sm font-medium text-gray-800",children:"WebUI 访问密码"}),o.jsx("div",{className:"text-xs text-gray-500 mt-0.5",children:"用于保护 WebUI 访问的密码"})]})]}),o.jsxs("button",{onClick:n,className:"px-4 py-2 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg text-sm font-medium hover:shadow-lg transition-all flex items-center gap-2",children:[o.jsx(Cp,{size:16}),"修改密码"]})]})]})]})};function Fc(e,t){const n=e.trim();return n?t!==void 0&&n.length<t?{isValid:!1,error:`密码长度不能少于${t}位`}:/[\r\n]/.test(n)?{isValid:!1,error:"密码不能包含换行符!"}:/[^\x20-\x7E\t]/.test(n)?{isValid:!1,error:"密码不能包含中文等特殊字符!"}:/[\x00-\x08\x0A-\x1F\x7F]/.test(n)?{isValid:!1,error:"密码包含不可见的控制字符!"}:{isValid:!0}:{isValid:!1,error:"密码不能为空"}}const as=({visible:e,onConfirm:t,onClose:n,error:r})=>{const[l,s]=C.useState(""),[i,a]=C.useState(!1),[u,d]=C.useState(""),g=C.useRef(null);C.useEffect(()=>{e&&g.current&&setTimeout(()=>{var v;return(v=g.current)==null?void 0:v.focus()},100)},[e]),C.useEffect(()=>{e&&(s(""),a(!1),d(""))},[e]);const h=()=>{const v=Fc(l);if(!v.isValid){d(v.error||"密码验证失败");return}d(""),t(l.trim())},m=v=>{v.key==="Enter"&&h()};return C.useEffect(()=>{if(!e)return;const v=y=>{y.key==="Escape"&&(y.preventDefault(),y.stopPropagation())};return window.addEventListener("keydown",v),()=>window.removeEventListener("keydown",v)},[e]),e?o.jsx(o.Fragment,{children:o.jsx("div",{className:"fixed inset-0 bg-black/30 backdrop-blur-sm flex items-center justify-center p-4",style:{zIndex:9e3},onClick:v=>v.target===v.currentTarget&&(n==null?void 0:n()),children:o.jsxs("div",{className:"bg-white/90 backdrop-blur-xl rounded-3xl shadow-2xl w-full max-w-md transform transition-all",children:[o.jsxs("div",{className:"flex items-center justify-between p-6 border-b border-white/20",children:[o.jsx("h3",{className:"text-xl font-semibold text-gray-900",children:r||"WebUI 密码"}),n&&o.jsx("button",{onClick:n,className:"text-gray-400 hover:text-gray-600 transition-colors",children:o.jsx(sr,{size:24})})]}),o.jsx("div",{className:"p-6",children:o.jsxs("div",{className:"space-y-2",children:[o.jsxs("div",{className:"relative",children:[o.jsx("input",{ref:g,type:i?"text":"password",value:l,onChange:v=>{s(v.target.value),u&&d("")},onKeyPress:m,placeholder:"请输入密码(支持数字、字母、符号)",className:`w-full px-4 py-3 pr-12 border rounded-xl focus:outline-none focus:ring-2 transition-all bg-white/50 backdrop-blur-sm ${u?"border-red-300 focus:ring-red-500 focus:border-red-500":"border-gray-300 focus:ring-blue-500 focus:border-transparent"}`,autoComplete:"off"}),o.jsx("button",{type:"button",onClick:()=>a(!i),className:"absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors",children:i?o.jsx(hn,{size:20}):o.jsx(gn,{size:20})})]}),u&&o.jsx("p",{className:"text-sm text-red-500 px-1",children:u})]})}),o.jsxs("div",{className:"flex items-center justify-end gap-3 p-6 border-t border-white/20",children:[n&&o.jsx("button",{onClick:n,className:"px-6 py-2.5 text-gray-700 hover:bg-gray-100 rounded-lg font-medium transition-colors",children:"取消"}),o.jsx("button",{onClick:h,disabled:!l.trim(),className:"px-6 py-2.5 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg font-medium hover:shadow-lg transition-all disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:shadow-none",children:"确定"})]})]})})}):null};function Ap(e){const t=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],r=new TextEncoder().encode(e),l=r.length*8,s=Math.ceil((l+65)/512)*64,i=new Uint8Array(s);i.set(r),i[r.length]=128;const a=new DataView(i.buffer);a.setUint32(s-4,l&4294967295,!1);let u=1779033703,d=3144134277,g=1013904242,h=2773480762,m=1359893119,v=2600822924,y=528734635,k=1541459225;for(let w=0;w<s;w+=64){const f=new Uint32Array(64);for(let b=0;b<16;b++)f[b]=a.getUint32(w+b*4,!1);for(let b=16;b<64;b++){const L=(f[b-15]>>>7|f[b-15]<<25)^(f[b-15]>>>18|f[b-15]<<14)^f[b-15]>>>3,M=(f[b-2]>>>17|f[b-2]<<15)^(f[b-2]>>>19|f[b-2]<<13)^f[b-2]>>>10;f[b]=f[b-16]+L+f[b-7]+M>>>0}let c=u,p=d,x=g,N=h,E=m,z=v,_=y,F=k;for(let b=0;b<64;b++){const L=(E>>>6|E<<26)^(E>>>11|E<<21)^(E>>>25|E<<7),M=E&z^~E&_,S=F+L+M+t[b]+f[b]>>>0,O=(c>>>2|c<<30)^(c>>>13|c<<19)^(c>>>22|c<<10),X=c&p^c&x^p&x,I=O+X>>>0;F=_,_=z,z=E,E=N+S>>>0,N=x,x=p,p=c,c=S+I>>>0}u=u+c>>>0,d=d+p>>>0,g=g+x>>>0,h=h+N>>>0,m=m+E>>>0,v=v+z>>>0,y=y+_>>>0,k=k+F>>>0}return[u.toString(16).padStart(8,"0"),d.toString(16).padStart(8,"0"),g.toString(16).padStart(8,"0"),h.toString(16).padStart(8,"0"),m.toString(16).padStart(8,"0"),v.toString(16).padStart(8,"0"),y.toString(16).padStart(8,"0"),k.toString(16).padStart(8,"0")].join("")}async function Up(e){try{return Ap(e)}catch(t){if(console.error("[PasswordHash] 纯JS SHA-256实现失败:",t),typeof crypto<"u"&&crypto.subtle)try{const n=new TextEncoder().encode(e),r=await crypto.subtle.digest("SHA-256",n);return Array.from(new Uint8Array(r)).map(s=>s.toString(16).padStart(2,"0")).join("")}catch(n){console.error("[PasswordHash] Web Crypto API失败:",n)}throw new Error("无法计算SHA-256哈希")}}async function ha(e){return await Up(e)}function $p(e,t,n=30){const r=new Date;r.setTime(r.getTime()+n*24*60*60*1e3);const l=`expires=${r.toUTCString()}`,i=window.location.protocol==="https:"?"; Secure":"",a=window.location.hostname,d=/^\d+\.\d+\.\d+\.\d+$/.test(a)?"":"; SameSite=Lax",g=`${e}=${t}; ${l}; path=/${d}${i}`;document.cookie=g}function Vp(e){const t=e+"=",n=document.cookie.split(";");for(let r=0;r<n.length;r++){let l=n[r];for(;l.charAt(0)===" ";)l=l.substring(1,l.length);if(l.indexOf(t)===0)return l.substring(t.length,l.length)}return console.log("[Cookie] 未找到Cookie:",{name:e,allCookies:document.cookie}),null}const Oc="webui_token",Bp=30;let Ln=null;function Hp(e){Ln=e}function Qp(){return Vp(Oc)}function ga(e){$p(Oc,e,Bp)}async function dt(e,t={}){const n=async r=>{const l={...t.headers};return r&&(l["x-webui-token"]=r),fetch(e,{...t,headers:l})};try{let r=await n(Qp());if(r.status===401&&Ln){console.log("401 - Password not set, prompting to set password...");const l=await Ln("请设置密码");if(!l||!l.trim())throw new Error("密码不能为空");if(!(await fetch("/api/set-token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:l.trim()})})).ok)throw new Error("设置密码失败");const i=await ha(l.trim());ga(i),r=await n(i)}if(r.status===403&&Ln){console.log("403 - Token verification failed, prompting for password...");let l=null;try{l=await r.clone().json()}catch{}l!=null&&l.locked&&ae(l.message||"账户已被锁定","error");let s=0;const i=5;for(;r.status===403&&s<i;)try{const a=s>0?"密码错误,请重新输入":"请输入密码",u=await Ln(a);if(!u||!u.trim())throw new Error("密码不能为空");const d=await ha(u.trim());if(ga(d),r=await n(d),r.status===200){console.log("Authentication successful!");break}try{if(l=await r.clone().json(),l!=null&&l.locked)throw new Error(l.message||"账户已被锁定")}catch{}s++}catch(a){throw console.error("Password prompt error:",a),a}if(r.status===403)throw new Error((l==null?void 0:l.message)||"认证失败")}if(!r.ok){const l=await r.text();throw new Error(`HTTP error! status: ${r.status}, message: ${l}`)}return await r.json()}catch(r){throw console.error("API fetch error:",r),r}}const Wp=({visible:e,onClose:t,onSuccess:n})=>{const[r,l]=C.useState(""),[s,i]=C.useState(""),[a,u]=C.useState(!1),[d,g]=C.useState(!1),[h,m]=C.useState(!1),[v,y]=C.useState(""),k=C.useRef(null);C.useEffect(()=>{e&&k.current&&setTimeout(()=>{var c;return(c=k.current)==null?void 0:c.focus()},100)},[e]),C.useEffect(()=>{e&&(l(""),i(""),u(!1),g(!1),y(""))},[e]);const w=async()=>{const c=Fc(r,6);if(!c.isValid){y(c.error||"密码验证失败");return}if(r!==s){y("两次输入的密码不一致");return}m(!0),y("");try{const p=await dt("/api/set-token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:r})});p.success?(ae("密码修改成功","success"),n(),t()):y(p.message||"密码修改失败")}catch(p){y(p.message||"密码修改失败")}finally{m(!1)}},f=c=>{c.key==="Enter"&&w()};return e?o.jsx(o.Fragment,{children:o.jsx("div",{className:"fixed inset-0 bg-black/30 backdrop-blur-sm flex items-center justify-center p-4",style:{zIndex:9e3},onClick:c=>c.target===c.currentTarget&&t(),children:o.jsxs("div",{className:"bg-white/90 backdrop-blur-xl rounded-3xl shadow-2xl w-full max-w-md transform transition-all",children:[o.jsxs("div",{className:"flex items-center gap-3 p-6 border-b border-white/20",children:[o.jsx("div",{className:"w-10 h-10 rounded-xl bg-gradient-to-br from-red-500 to-pink-600 flex items-center justify-center",children:o.jsx(Mc,{size:20,className:"text-white"})}),o.jsxs("div",{className:"flex-1",children:[o.jsx("h3",{className:"text-xl font-semibold text-gray-900",children:"修改 WebUI 密码"}),o.jsx("p",{className:"text-sm text-gray-600 mt-0.5",children:"请输入新密码"})]}),o.jsx("button",{onClick:t,className:"text-gray-400 hover:text-gray-600 transition-colors",children:o.jsx(sr,{size:24})})]}),o.jsxs("div",{className:"p-6 space-y-4",children:[v&&o.jsx("div",{className:"p-3 bg-red-50 border border-red-200 rounded-xl text-red-600 text-sm",children:v}),o.jsxs("div",{children:[o.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-2",children:"新密码"}),o.jsxs("div",{className:"relative",children:[o.jsx("input",{ref:k,type:a?"text":"password",value:r,onChange:c=>{l(c.target.value),y("")},onKeyPress:f,placeholder:"请输入新密码(支持数字、字母、符号)",className:"w-full px-4 py-3 pr-12 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all bg-white/50 backdrop-blur-sm",autoComplete:"new-password"}),o.jsx("button",{type:"button",onClick:()=>u(!a),className:"absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors",children:a?o.jsx(hn,{size:20}):o.jsx(gn,{size:20})})]}),o.jsx("p",{className:"text-xs text-gray-500 mt-1",children:"密码长度至少6位"})]}),o.jsxs("div",{children:[o.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-2",children:"确认密码"}),o.jsxs("div",{className:"relative",children:[o.jsx("input",{type:d?"text":"password",value:s,onChange:c=>{i(c.target.value),y("")},onKeyPress:f,placeholder:"请再次输入新密码",className:"w-full px-4 py-3 pr-12 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all bg-white/50 backdrop-blur-sm",autoComplete:"new-password"}),o.jsx("button",{type:"button",onClick:()=>g(!d),className:"absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors",children:d?o.jsx(hn,{size:20}):o.jsx(gn,{size:20})})]})]})]}),o.jsxs("div",{className:"flex items-center justify-end gap-3 p-6 border-t border-white/20",children:[o.jsx("button",{onClick:t,disabled:h,className:"px-6 py-2.5 text-gray-700 hover:bg-gray-100 rounded-lg font-medium transition-colors disabled:opacity-50",children:"取消"}),o.jsx("button",{onClick:w,disabled:h||!r.trim()||!s.trim(),className:"px-6 py-2.5 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg font-medium hover:shadow-lg transition-all disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:shadow-none",children:h?"修改中...":"确定修改"})]})]})})}):null},Kp=({onLoginSuccess:e})=>{const[t,n]=C.useState("quick"),[r,l]=C.useState(!1),[s,i]=C.useState(!1),[a,u]=C.useState(!1),[d,g]=C.useState(""),[h,m]=C.useState([]),[v,y]=C.useState(null),[k,w]=C.useState(!1),f=C.useRef(null),c=C.useRef(null),p=C.useRef(null),x=C.useRef(!1),N={scanning:"扫描成功,请在手机上确认",success:"登录成功",expired:"二维码已过期,请刷新",error:"登录失败,请重试","":""},E=C.useCallback(()=>{x.current=!1,p.current&&(clearTimeout(p.current),p.current=null)},[]),z=C.useCallback(async()=>{if(x.current)return;x.current=!0,console.log("开始轮询登录状态...");const I=60;let oe=0;const P=async()=>{if(oe>=I){E(),ae("登录超时,请重试","error"),t==="qr"&&g("error");return}oe++;try{const R=await dt("/api/login-info");if(R.success&&R.data.online===!0){E(),ae("登录成功!正在跳转到主页面...","success"),t==="qr"&&g("success"),setTimeout(()=>{e()},1e3);return}p.current=setTimeout(P,3e3)}catch(R){console.warn("轮询登录状态失败:",R),p.current=setTimeout(P,3e3)}};await P()},[t,e,E]),_=C.useCallback(I=>{if(!f.current)return;const P=f.current.getContext("2d");if(!P)return;const R=new Image;R.onload=()=>{P.clearRect(0,0,200,200),P.drawImage(R,0,0,200,200)},R.src=I},[]),F=C.useCallback(async()=>{if(f.current)try{const I=await dt("/api/login-qrcode");if(I.success&&I.data){_(I.data.pngBase64QrcodeData);const oe=I.data.expireTime*1e3;c.current&&clearInterval(c.current),c.current=setTimeout(()=>{u(!0),g("expired"),E()},oe),u(!1),g(""),ae("请使用手机QQ扫码登录","warning"),await z()}else throw new Error(I.message||"获取二维码失败")}catch(I){ae(I.message||"获取二维码失败","error"),console.error("QR code generation error:",I)}},[_,z,E]),b=C.useCallback(async()=>{await F(),ae("二维码已刷新","success")},[F]),L=C.useRef(!1),M=C.useCallback(async()=>{if(!L.current){L.current=!0;try{const I=await dt("/api/quick-login-list");if(console.log("Quick login list response:",I),I.success&&I.data&&I.data.LocalLoginInfoList){const oe=I.data.LocalLoginInfoList.filter(P=>P.isQuickLogin&&!P.isUserLogin);m(oe),console.log("Accounts loaded:",oe),oe.length>0?y(P=>P??oe[0]):n("qr")}else console.warn("No quick login accounts available:",I.message),m([])}catch(I){console.error("Failed to fetch quick login list:",I),ae("获取快速登录列表失败","error"),m([])}}},[]),S=C.useCallback(async()=>{if(v){i(!0);try{const oe=(await dt("/api/quick-login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({uin:v.uin})})).data;if(oe.result==="0")ae(`正在登录 ${v.nickName}...`,"success"),await z();else throw new Error(oe.loginErrorInfo.errMsg||"登录失败")}catch(I){ae(I.message,"error"),console.error("Quick login error:",I),n("qr")}finally{i(!1)}}},[v,z]),O=()=>{l(!r)},X=I=>{y(I),l(!1)};return C.useEffect(()=>(L.current||M(),()=>{c.current&&clearInterval(c.current),E()}),[]),C.useEffect(()=>{t==="qr"?setTimeout(()=>F(),100):c.current&&clearInterval(c.current),t==="quick"&&h.length===0&&!L.current&&M()},[t,h.length,F]),o.jsx("div",{className:"relative min-h-screen flex flex-col items-center justify-center p-5",children:o.jsxs("div",{className:"bg-white/50 backdrop-blur-2xl rounded-3xl p-10 shadow-xl border border-white/30 min-w-[320px] text-center relative z-10",children:[t==="quick"&&o.jsxs("div",{className:"flex flex-col items-center gap-6",children:[!r&&v&&o.jsxs("div",{className:"flex flex-col items-center cursor-pointer p-4 rounded-2xl transition-colors hover:bg-blue-50",onClick:O,children:[o.jsx("div",{className:"w-20 h-20 rounded-full overflow-hidden mb-3 shadow-lg",children:o.jsx("img",{src:v.faceUrl,alt:v.nickName,className:"w-full h-full object-cover"})}),o.jsx("div",{className:"text-base text-gray-800 mb-2",children:v.nickName})]}),r&&o.jsx("div",{className:"grid grid-cols-2 gap-4 my-5 w-full max-w-md",children:h.map(I=>o.jsxs("div",{className:"flex flex-col items-center p-4 rounded-2xl cursor-pointer transition-all border-2 border-transparent hover:bg-blue-50 hover:border-blue-500",onClick:()=>X(I),children:[o.jsx("div",{className:"w-[60px] h-[60px] rounded-full overflow-hidden mb-2 shadow-md",children:o.jsx("img",{src:I.faceUrl,alt:I.nickName,className:"w-full h-full object-cover"})}),o.jsx("div",{className:"text-sm text-gray-800 text-center truncate w-full px-1",children:I.nickName})]},I.uin))}),!r&&o.jsx("button",{onClick:S,disabled:!v||s,className:"w-[280px] h-11 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-full font-medium text-base disabled:opacity-50 disabled:cursor-not-allowed hover:shadow-lg transition-all flex items-center justify-center gap-2",children:s?o.jsxs(o.Fragment,{children:[o.jsx(Vt,{size:20,className:"animate-spin"}),"登录中..."]}):"登录"}),o.jsxs("div",{className:"flex gap-6 justify-center",children:[!r&&o.jsx("button",{onClick:O,className:"text-blue-600 text-sm hover:underline",children:"切换账号"}),o.jsx("button",{onClick:()=>n("qr"),className:"text-blue-600 text-sm hover:underline",children:"扫码登录"})]})]}),t==="qr"&&o.jsxs("div",{className:"flex flex-col items-center gap-5",children:[o.jsx("div",{className:"relative inline-block",children:o.jsxs("div",{className:"relative p-5 bg-white rounded-2xl shadow-lg",children:[o.jsx("canvas",{ref:f,width:"200",height:"200",className:"block rounded-lg"}),a&&o.jsxs("div",{className:"absolute inset-0 bg-black/70 flex flex-col items-center justify-center text-white cursor-pointer rounded-2xl transition-opacity hover:opacity-90",onClick:b,children:[o.jsx(Pp,{size:32,className:"mb-2"}),o.jsx("div",{children:"点击刷新"})]})]})}),o.jsx("div",{className:"text-gray-600",children:"请使用手机QQ扫码登录"}),d&&o.jsx("div",{className:`text-sm px-4 py-2 rounded-lg ${d==="success"?"bg-green-100 text-green-800":d==="error"||d==="expired"?"bg-red-100 text-red-800":"bg-blue-100 text-blue-800"}`,children:N[d]})]}),o.jsx("div",{className:"mt-6",children:t==="qr"&&h.length>0&&o.jsx("button",{onClick:()=>n("quick"),className:"text-blue-600 text-sm hover:underline",children:"快速登录"})})]})})},qp=!1,Gp=()=>({friendCount:128,groupCount:45,messageReceived:12580,messageSent:3842,startupTime:Math.floor(Date.now()/1e3)-3600*5-1234,lastMessageTime:Math.floor(Date.now()/1e3)-30,bot:{memory:(80+Math.random()*40)*1024*1024,totalMemory:16*1024*1024*1024,memoryPercent:2+Math.random()*3,cpu:3+Math.random()*10},qq:{memory:(200+Math.random()*100)*1024*1024,totalMemory:16*1024*1024*1024,memoryPercent:5+Math.random()*8,cpu:5+Math.random()*15}}),ya=e=>!e||e<=0?"0 MB":e<1024?e+" B":e<1024*1024?(e/1024).toFixed(1)+" KB":e<1024*1024*1024?(e/1024/1024).toFixed(0)+" MB":(e/1024/1024/1024).toFixed(2)+" GB",Yp=e=>{const n=Math.floor(Date.now()/1e3)-e,r=Math.floor(n/86400),l=Math.floor(n%86400/3600),s=Math.floor(n%3600/60),i=n%60;return r>0?`${r}天 ${l}时 ${s}分`:l>0?`${l}时 ${s}分 ${i}秒`:s>0?`${s}分 ${i}秒`:`${i}秒`},Xp=e=>e?new Date(e*1e3).toLocaleString("zh-CN"):"暂无",_r=({icon:e,label:t,value:n,gradient:r})=>o.jsxs("div",{className:"flex items-center gap-3 p-3 rounded-xl bg-white/30 hover:bg-white/50 transition-all duration-200 hover:scale-[1.02]",children:[o.jsx("div",{className:`w-10 h-10 rounded-xl ${r} flex items-center justify-center shadow-md`,children:e}),o.jsxs("div",{className:"flex-1 min-w-0",children:[o.jsx("p",{className:"text-xs text-gray-500",children:t}),o.jsx("p",{className:"text-lg font-bold text-gray-800 truncate",children:n})]})]}),xa=({value:e,size:t=100,strokeWidth:n=8,gradientId:r,gradientColors:l,label:s,displayValue:i,icon:a})=>{const u=(t-n)/2,d=u*2*Math.PI,g=Math.min(Math.max(e,0),100),h=d-g/100*d;return o.jsxs("div",{className:"flex flex-col items-center",children:[o.jsxs("div",{className:"relative",style:{width:t,height:t},children:[o.jsxs("svg",{width:t,height:t,className:"transform -rotate-90",children:[o.jsx("defs",{children:o.jsxs("linearGradient",{id:r,x1:"0%",y1:"0%",x2:"100%",y2:"100%",children:[o.jsx("stop",{offset:"0%",stopColor:l[0]}),o.jsx("stop",{offset:"100%",stopColor:l[1]})]})}),o.jsx("circle",{cx:t/2,cy:t/2,r:u,fill:"none",stroke:"rgba(0,0,0,0.06)",strokeWidth:n}),o.jsx("circle",{cx:t/2,cy:t/2,r:u,fill:"none",stroke:`url(#${r})`,strokeWidth:n,strokeDasharray:d,strokeDashoffset:h,strokeLinecap:"round",className:"transition-all duration-1000 ease-out"})]}),o.jsxs("div",{className:"absolute inset-0 flex flex-col items-center justify-center",children:[o.jsx("div",{className:"w-8 h-8 rounded-lg flex items-center justify-center shadow-md",style:{background:`linear-gradient(135deg, ${l[0]}, ${l[1]})`},children:a}),o.jsxs("span",{className:"text-sm font-bold text-gray-800 mt-1",children:[g.toFixed(1),"%"]})]})]}),o.jsx("p",{className:"text-xs font-semibold text-gray-700 mt-2",children:s}),o.jsx("p",{className:"text-xs text-gray-500",children:i})]})},va=({title:e,icon:t,gradient:n,cpu:r,memory:l,totalMemory:s,memoryPercent:i,cpuGradientId:a,memGradientId:u,cpuColors:d,memColors:g})=>o.jsxs("div",{className:"card p-4",children:[o.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[o.jsx("div",{className:`w-8 h-8 rounded-lg ${n} flex items-center justify-center shadow-md`,children:t}),o.jsx("h4",{className:"text-sm font-semibold text-gray-800",children:e})]}),o.jsxs("div",{className:"flex justify-around",children:[o.jsx(xa,{value:r,gradientId:a,gradientColors:d,label:"CPU",displayValue:`${r.toFixed(1)}%`,icon:o.jsx(Lc,{size:16,className:"text-white"})}),o.jsx(xa,{value:i,gradientId:u,gradientColors:g,label:"内存",displayValue:`${ya(l)} / ${ya(s)}`,icon:o.jsx(xp,{size:16,className:"text-white"})})]})]}),Zp=()=>{const[e,t]=C.useState(null),[n,r]=C.useState(!0),[l,s]=C.useState(""),i=C.useRef(),a=async()=>{try{const u=qp?Gp():(await dt("/api/dashboard/stats")).data;u&&t(u)}catch(u){console.error("Failed to fetch dashboard stats:",u)}finally{r(!1)}};return C.useEffect(()=>(a(),i.current=window.setInterval(a,5e3),()=>{i.current&&clearInterval(i.current)}),[]),C.useEffect(()=>{if(!(e!=null&&e.startupTime))return;const u=()=>s(Yp(e.startupTime));u();const d=setInterval(u,1e3);return()=>clearInterval(d)},[e==null?void 0:e.startupTime]),n?o.jsx("div",{className:"flex items-center justify-center h-64",children:o.jsx("div",{className:"w-12 h-12 border-4 border-blue-500 border-t-transparent rounded-full animate-spin"})}):e?o.jsxs("div",{className:"space-y-5",children:[o.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-4",children:[o.jsxs("div",{className:"card p-4 flex flex-col",children:[o.jsxs("div",{className:"flex items-center gap-3 mb-3",children:[o.jsx("div",{className:"w-10 h-10 rounded-xl bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center shadow-md",children:o.jsx(Br,{size:20,className:"text-white"})}),o.jsx("h3",{className:"text-base font-semibold text-gray-800",children:"运行时间"}),o.jsxs("div",{className:"ml-auto flex items-center gap-1 px-2 py-0.5 rounded-full bg-green-100 text-green-600 text-xs font-medium",children:[o.jsx(Mp,{size:12}),"运行中"]})]}),o.jsxs("div",{className:"flex-1 flex flex-col justify-center space-y-2",children:[o.jsxs("div",{className:"p-3 rounded-xl bg-gradient-to-r from-indigo-50 to-purple-50",children:[o.jsx("p",{className:"text-xs text-gray-500",children:"已运行"}),o.jsx("p",{className:"text-xl font-bold bg-gradient-to-r from-indigo-600 to-purple-600 bg-clip-text text-transparent",children:l})]}),o.jsxs("div",{className:"px-3 py-2",children:[o.jsx("p",{className:"text-xs text-gray-500",children:"启动时间"}),o.jsx("p",{className:"text-sm font-medium text-gray-700",children:Xp(e.startupTime)})]})]})]}),o.jsxs("div",{className:"card p-4 space-y-3",children:[o.jsx(_r,{icon:o.jsx(Tp,{size:20,className:"text-white"}),label:"好友数量",value:e.friendCount.toLocaleString(),gradient:"bg-gradient-to-br from-blue-500 to-cyan-500"}),o.jsx(_r,{icon:o.jsx(_p,{size:20,className:"text-white"}),label:"群组数量",value:e.groupCount.toLocaleString(),gradient:"bg-gradient-to-br from-purple-500 to-pink-500"})]}),o.jsxs("div",{className:"card p-4 space-y-3",children:[o.jsx(_r,{icon:o.jsx(jp,{size:20,className:"text-white"}),label:"收到消息",value:e.messageReceived.toLocaleString(),gradient:"bg-gradient-to-br from-green-500 to-emerald-500"}),o.jsx(_r,{icon:o.jsx(lo,{size:20,className:"text-white"}),label:"发送消息",value:e.messageSent.toLocaleString(),gradient:"bg-gradient-to-br from-orange-500 to-amber-500"})]})]}),o.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[o.jsx(va,{title:"QQ 资源",icon:o.jsx(wp,{size:16,className:"text-white"}),gradient:"bg-gradient-to-br from-blue-500 to-cyan-500",cpu:e.qq.cpu,memory:e.qq.memory,totalMemory:e.qq.totalMemory,memoryPercent:e.qq.memoryPercent,cpuGradientId:"qqCpuGradient",memGradientId:"qqMemGradient",cpuColors:["#3b82f6","#06b6d4"],memColors:["#0ea5e9","#22d3ee"]}),o.jsx(va,{title:"Bot 资源",icon:o.jsx(hp,{size:16,className:"text-white"}),gradient:"bg-gradient-to-br from-violet-500 to-purple-600",cpu:e.bot.cpu,memory:e.bot.memory,totalMemory:e.bot.totalMemory,memoryPercent:e.bot.memoryPercent,cpuGradientId:"botCpuGradient",memGradientId:"botMemGradient",cpuColors:["#8b5cf6","#a855f7"],memColors:["#6366f1","#8b5cf6"]})]})]}):o.jsx("div",{className:"card p-8 text-center",children:o.jsx("p",{className:"text-gray-500",children:"无法加载统计数据"})})},us=()=>{const e=C.useRef(null),t=C.useRef([]),n=C.useRef(),r=C.useRef(0);return C.useEffect(()=>{const l=e.current;if(!l)return;const s=l.getContext("2d",{alpha:!0});if(!s)return;const a=1e3/30,u=()=>{l.width=window.innerWidth,l.height=window.innerHeight,t.current.forEach(y=>{y.offscreenCanvas=g(y)})},d=["rgba(139, 92, 246, 0.6)","rgba(59, 130, 246, 0.6)","rgba(236, 72, 153, 0.6)","rgba(16, 185, 129, 0.6)","rgba(245, 158, 11, 0.6)","rgba(168, 85, 247, 0.6)","rgba(14, 165, 233, 0.6)","rgba(251, 113, 133, 0.6)"],g=y=>{const k=Math.ceil(y.baseRadius*2.5),w=document.createElement("canvas");w.width=k,w.height=k;const f=w.getContext("2d");if(!f)return w;const c=k/2,p=k/2,x=y.baseRadius,N=f.createRadialGradient(c,p,0,c,p,x);return N.addColorStop(0,y.color.replace("0.6","0.8")),N.addColorStop(.5,y.color),N.addColorStop(1,y.color.replace("0.6","0")),f.fillStyle=N,f.beginPath(),f.arc(c,p,x,0,Math.PI*2),f.fill(),w},h=()=>{const y=[];for(let w=0;w<8;w++){const f=Math.random()*80+60,c={x:Math.random()*l.width,y:Math.random()*l.height,vx:(Math.random()-.5)*.8,vy:(Math.random()-.5)*.8,radius:f,baseRadius:f,scale:1,scaleSpeed:Math.random()*.002+.001,color:d[Math.floor(Math.random()*d.length)]};c.offscreenCanvas=g(c),y.push(c)}t.current=y},m=(y,k)=>{const w=k.x-y.x,f=k.y-y.y,c=Math.sqrt(w*w+f*f);if(c<y.radius+k.radius){const p=Math.atan2(f,w),x=Math.sin(p),N=Math.cos(p),E=y.vx*N+y.vy*x,z=y.vy*N-y.vx*x,_=k.vx*N+k.vy*x,F=k.vy*N-k.vx*x;y.vx=_*N-z*x,y.vy=z*N+_*x,k.vx=E*N-F*x,k.vy=F*N+E*x;const b=(y.radius+k.radius-c)/2;y.x-=b*N,y.y-=b*x,k.x+=b*N,k.y+=b*x}},v=y=>{n.current=requestAnimationFrame(v);const k=y-r.current;k<a||(r.current=y-k%a,s.clearRect(0,0,l.width,l.height),t.current.forEach((w,f)=>{w.x+=w.vx,w.y+=w.vy,w.scale+=w.scaleSpeed,(w.scale>1.2||w.scale<.8)&&(w.scaleSpeed=-w.scaleSpeed),w.radius=w.baseRadius*w.scale,(w.x-w.radius<0||w.x+w.radius>l.width)&&(w.vx=-w.vx,w.x=Math.max(w.radius,Math.min(l.width-w.radius,w.x))),(w.y-w.radius<0||w.y+w.radius>l.height)&&(w.vy=-w.vy,w.y=Math.max(w.radius,Math.min(l.height-w.radius,w.y)));for(let c=f+1;c<t.current.length;c++)m(w,t.current[c]);if(w.offscreenCanvas){const c=w.offscreenCanvas.width*w.scale;s.drawImage(w.offscreenCanvas,w.x-c/2,w.y-c/2,c,c)}}))};return u(),window.addEventListener("resize",u),h(),n.current=requestAnimationFrame(v),()=>{window.removeEventListener("resize",u),n.current&&cancelAnimationFrame(n.current)}},[]),o.jsx("canvas",{ref:e,className:"fixed inset-0 w-full h-full pointer-events-none",style:{zIndex:0}})},Jp={enable:!0,connect:[]},e0={enable:!1,port:5600,token:""},t0={enable:!1,reportSelfMessage:!1,http:{port:3010,prefix:"",accessToken:""},webhook:{urls:[]}},n0={enable:!0,port:3080},r0={webui:n0,onlyLocalhost:!0,milky:t0,satori:e0,ob11:Jp,enableLocalFile2Url:!1,log:!0,autoDeleteFile:!1,autoDeleteFileSecond:60,musicSignUrl:"https://llob.linyuchen.net/sign/music",msgCacheExpire:120,ffmpeg:"",rawMsgPB:!1},l0="7.1.1";function s0(){const[e,t]=C.useState("dashboard"),[n,r]=C.useState(r0),[l,s]=C.useState(!1),[i,a]=C.useState(!1),[u,d]=C.useState(!0),[g,h]=C.useState(null),[m,v]=C.useState(!1),[y,k]=C.useState(""),[w,f]=C.useState(null),[c,p]=C.useState(!1),[x,N]=C.useState(!1),[E,z]=C.useState(!1);C.useEffect(()=>{Hp(async L=>new Promise(M=>{k(L||""),v(!0),f(()=>M)}))},[]);const _=C.useCallback(L=>{L.trim()?(v(!1),k(""),w&&(w(L),f(null))):k("密码不能为空")},[w]);C.useEffect(()=>{(async()=>{try{const M=await dt("/api/config");M.success&&M.data.selfInfo.online?(a(!0),h({nick:M.data.selfInfo.nick||"",uin:M.data.selfInfo.uin}),r(M.data.config)):a(!1)}catch(M){console.error("Failed to check login status:",M),a(!1)}finally{d(!1)}})()},[]);const F=C.useCallback(async L=>{try{s(!0);const S=await dt("/api/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({config:L||n})});S.success?ae("配置保存成功","success"):ae("保存失败:"+S.message,"error")}catch(M){ae("保存失败:"+M.message,"error")}finally{s(!1)}},[n]),b=C.useCallback(()=>{window.location.reload()},[]);return u?o.jsxs(o.Fragment,{children:[o.jsx(us,{}),o.jsx("div",{className:"relative flex items-center justify-center min-h-screen z-10",children:o.jsx(Vt,{size:48,className:"animate-spin text-blue-500"})}),o.jsx(as,{visible:m,onConfirm:_,error:y})]}):i?o.jsxs("div",{className:"flex min-h-screen",children:[o.jsx(us,{}),o.jsx(Rp,{activeTab:e,onTabChange:t,accountInfo:g||void 0}),o.jsx("main",{className:"flex-1 p-8 overflow-auto z-10",children:o.jsxs("div",{className:"max-w-6xl mx-auto",children:[o.jsxs("div",{className:"mb-8",children:[o.jsx("h2",{className:"text-3xl font-bold text-white mb-2",children:e==="dashboard"&&"Dashboard"}),o.jsx("p",{className:"text-white/80",children:e==="dashboard"&&"欢迎使用 Lucky Lillia Bot"})]}),e==="dashboard"&&o.jsx(Zp,{}),e==="onebot"&&o.jsx(Op,{config:n.ob11,globalConfig:n,onChange:L=>{const M={...n,ob11:L};r(M)},onSave:L=>{if(L){const M={...n,ob11:L};F(M)}else F()}}),e==="satori"&&o.jsxs("div",{className:"card p-6",children:[o.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[o.jsx("div",{className:"w-12 h-12 rounded-xl bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center",children:o.jsx(so,{size:24,className:"text-white"})}),o.jsxs("div",{children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"Satori 协议"}),o.jsx("p",{className:"text-sm text-gray-600",children:"配置 Satori 协议相关设置"})]})]}),o.jsxs("div",{className:"space-y-4",children:[o.jsxs("div",{className:"flex items-center justify-between p-4 bg-gray-50/50 rounded-xl hover:bg-gray-100/50 transition-colors",children:[o.jsxs("div",{children:[o.jsx("div",{className:"text-sm font-medium text-gray-800",children:"启用 Satori 协议"}),o.jsx("div",{className:"text-xs text-gray-500 mt-0.5",children:"开启后将支持 Satori 协议连接"})]}),o.jsx("input",{type:"checkbox",checked:n.satori.enable,onChange:L=>r({...n,satori:{...n.satori,enable:L.target.checked}}),className:`w-12 h-6 rounded-full bg-gray-300 relative cursor-pointer appearance-none\r
|
|
290
|
+
checked:before:translate-x-6`})]}),e.autoDeleteFile&&o.jsx("div",{className:"pl-4",children:o.jsxs("label",{className:"block",children:[o.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[o.jsx(Br,{size:16,className:"text-gray-600"}),o.jsx("span",{className:"text-sm font-medium text-gray-700",children:"自动删除时间(秒)"})]}),o.jsx("input",{type:"number",value:e.autoDeleteFileSecond,onChange:l=>r("autoDeleteFileSecond",parseInt(l.target.value)),min:"1",max:"3600",className:"input-field",placeholder:"60"}),o.jsx("p",{className:"text-xs text-gray-500 mt-1",children:"文件接收后多少秒自动删除(1-3600秒)"})]})})]})]}),o.jsxs("div",{className:"card p-6",children:[o.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[o.jsx("div",{className:"w-10 h-10 rounded-xl bg-gradient-to-br from-purple-500 to-pink-600 flex items-center justify-center",children:o.jsx(Br,{size:20,className:"text-white"})}),o.jsxs("div",{children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"缓存设置"}),o.jsx("p",{className:"text-sm text-gray-600",children:"消息缓存相关配置"})]})]}),o.jsxs("label",{className:"block",children:[o.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[o.jsx(Br,{size:16,className:"text-purple-600"}),o.jsx("span",{className:"text-sm font-medium text-gray-700",children:"消息缓存过期时间(秒)"})]}),o.jsx("input",{type:"number",value:e.msgCacheExpire,onChange:l=>r("msgCacheExpire",parseInt(l.target.value)),min:"1",max:"86400",className:"input-field",placeholder:"3600"}),o.jsx("p",{className:"text-xs text-gray-500 mt-1",children:"消息在缓存中保留的时间(1-86400秒)"})]})]}),o.jsxs("div",{className:"card p-6",children:[o.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[o.jsx("div",{className:"w-10 h-10 rounded-xl bg-gradient-to-br from-green-500 to-teal-600 flex items-center justify-center",children:o.jsx(da,{size:20,className:"text-white"})}),o.jsxs("div",{children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"扩展功能"}),o.jsx("p",{className:"text-sm text-gray-600",children:"第三方服务配置"})]})]}),o.jsxs("label",{className:"block",children:[o.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[o.jsx(da,{size:16,className:"text-green-600"}),o.jsx("span",{className:"text-sm font-medium text-gray-700",children:"音乐签名地址"})]}),o.jsx("input",{type:"text",value:e.musicSignUrl,onChange:l=>r("musicSignUrl",l.target.value),placeholder:"https://example.com/sign",className:"input-field"}),o.jsx("p",{className:"text-xs text-gray-500 mt-1",children:"用于音乐卡片签名的服务地址"})]})]}),o.jsxs("div",{className:"card p-6",children:[o.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[o.jsx("div",{className:"w-10 h-10 rounded-xl bg-gradient-to-br from-red-500 to-pink-600 flex items-center justify-center",children:o.jsx(zp,{size:20,className:"text-white"})}),o.jsxs("div",{children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"安全设置"}),o.jsx("p",{className:"text-sm text-gray-600",children:"WebUI 访问控制"})]})]}),o.jsxs("div",{className:"flex items-center justify-between p-4 bg-gray-50/50 rounded-xl hover:bg-gray-100/50 transition-colors",children:[o.jsxs("div",{className:"flex items-center gap-3",children:[o.jsx(Mc,{size:20,className:"text-red-600"}),o.jsxs("div",{children:[o.jsx("div",{className:"text-sm font-medium text-gray-800",children:"WebUI 访问密码"}),o.jsx("div",{className:"text-xs text-gray-500 mt-0.5",children:"用于保护 WebUI 访问的密码"})]})]}),o.jsxs("button",{onClick:n,className:"px-4 py-2 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg text-sm font-medium hover:shadow-lg transition-all flex items-center gap-2",children:[o.jsx(Cp,{size:16}),"修改密码"]})]})]})]})};function Fc(e,t){const n=e.trim();return n?t!==void 0&&n.length<t?{isValid:!1,error:`密码长度不能少于${t}位`}:/[\r\n]/.test(n)?{isValid:!1,error:"密码不能包含换行符!"}:/[^\x20-\x7E\t]/.test(n)?{isValid:!1,error:"密码不能包含中文等特殊字符!"}:/[\x00-\x08\x0A-\x1F\x7F]/.test(n)?{isValid:!1,error:"密码包含不可见的控制字符!"}:{isValid:!0}:{isValid:!1,error:"密码不能为空"}}const as=({visible:e,onConfirm:t,onClose:n,error:r})=>{const[l,s]=C.useState(""),[i,a]=C.useState(!1),[u,d]=C.useState(""),g=C.useRef(null);C.useEffect(()=>{e&&g.current&&setTimeout(()=>{var v;return(v=g.current)==null?void 0:v.focus()},100)},[e]),C.useEffect(()=>{e&&(s(""),a(!1),d(""))},[e]);const h=()=>{const v=Fc(l);if(!v.isValid){d(v.error||"密码验证失败");return}d(""),t(l.trim())},m=v=>{v.key==="Enter"&&h()};return C.useEffect(()=>{if(!e)return;const v=y=>{y.key==="Escape"&&(y.preventDefault(),y.stopPropagation())};return window.addEventListener("keydown",v),()=>window.removeEventListener("keydown",v)},[e]),e?o.jsx(o.Fragment,{children:o.jsx("div",{className:"fixed inset-0 bg-black/30 backdrop-blur-sm flex items-center justify-center p-4",style:{zIndex:9e3},onClick:v=>v.target===v.currentTarget&&(n==null?void 0:n()),children:o.jsxs("div",{className:"bg-white/90 backdrop-blur-xl rounded-3xl shadow-2xl w-full max-w-md transform transition-all",children:[o.jsxs("div",{className:"flex items-center justify-between p-6 border-b border-white/20",children:[o.jsx("h3",{className:"text-xl font-semibold text-gray-900",children:r||"WebUI 密码"}),n&&o.jsx("button",{onClick:n,className:"text-gray-400 hover:text-gray-600 transition-colors",children:o.jsx(sr,{size:24})})]}),o.jsx("div",{className:"p-6",children:o.jsxs("div",{className:"space-y-2",children:[o.jsxs("div",{className:"relative",children:[o.jsx("input",{ref:g,type:i?"text":"password",value:l,onChange:v=>{s(v.target.value),u&&d("")},onKeyPress:m,placeholder:"请输入密码(支持数字、字母、符号)",className:`w-full px-4 py-3 pr-12 border rounded-xl focus:outline-none focus:ring-2 transition-all bg-white/50 backdrop-blur-sm ${u?"border-red-300 focus:ring-red-500 focus:border-red-500":"border-gray-300 focus:ring-blue-500 focus:border-transparent"}`,autoComplete:"off"}),o.jsx("button",{type:"button",onClick:()=>a(!i),className:"absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors",children:i?o.jsx(hn,{size:20}):o.jsx(gn,{size:20})})]}),u&&o.jsx("p",{className:"text-sm text-red-500 px-1",children:u})]})}),o.jsxs("div",{className:"flex items-center justify-end gap-3 p-6 border-t border-white/20",children:[n&&o.jsx("button",{onClick:n,className:"px-6 py-2.5 text-gray-700 hover:bg-gray-100 rounded-lg font-medium transition-colors",children:"取消"}),o.jsx("button",{onClick:h,disabled:!l.trim(),className:"px-6 py-2.5 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg font-medium hover:shadow-lg transition-all disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:shadow-none",children:"确定"})]})]})})}):null};function Ap(e){const t=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],r=new TextEncoder().encode(e),l=r.length*8,s=Math.ceil((l+65)/512)*64,i=new Uint8Array(s);i.set(r),i[r.length]=128;const a=new DataView(i.buffer);a.setUint32(s-4,l&4294967295,!1);let u=1779033703,d=3144134277,g=1013904242,h=2773480762,m=1359893119,v=2600822924,y=528734635,k=1541459225;for(let w=0;w<s;w+=64){const f=new Uint32Array(64);for(let b=0;b<16;b++)f[b]=a.getUint32(w+b*4,!1);for(let b=16;b<64;b++){const L=(f[b-15]>>>7|f[b-15]<<25)^(f[b-15]>>>18|f[b-15]<<14)^f[b-15]>>>3,M=(f[b-2]>>>17|f[b-2]<<15)^(f[b-2]>>>19|f[b-2]<<13)^f[b-2]>>>10;f[b]=f[b-16]+L+f[b-7]+M>>>0}let c=u,p=d,x=g,N=h,E=m,z=v,_=y,F=k;for(let b=0;b<64;b++){const L=(E>>>6|E<<26)^(E>>>11|E<<21)^(E>>>25|E<<7),M=E&z^~E&_,S=F+L+M+t[b]+f[b]>>>0,O=(c>>>2|c<<30)^(c>>>13|c<<19)^(c>>>22|c<<10),X=c&p^c&x^p&x,I=O+X>>>0;F=_,_=z,z=E,E=N+S>>>0,N=x,x=p,p=c,c=S+I>>>0}u=u+c>>>0,d=d+p>>>0,g=g+x>>>0,h=h+N>>>0,m=m+E>>>0,v=v+z>>>0,y=y+_>>>0,k=k+F>>>0}return[u.toString(16).padStart(8,"0"),d.toString(16).padStart(8,"0"),g.toString(16).padStart(8,"0"),h.toString(16).padStart(8,"0"),m.toString(16).padStart(8,"0"),v.toString(16).padStart(8,"0"),y.toString(16).padStart(8,"0"),k.toString(16).padStart(8,"0")].join("")}async function Up(e){try{return Ap(e)}catch(t){if(console.error("[PasswordHash] 纯JS SHA-256实现失败:",t),typeof crypto<"u"&&crypto.subtle)try{const n=new TextEncoder().encode(e),r=await crypto.subtle.digest("SHA-256",n);return Array.from(new Uint8Array(r)).map(s=>s.toString(16).padStart(2,"0")).join("")}catch(n){console.error("[PasswordHash] Web Crypto API失败:",n)}throw new Error("无法计算SHA-256哈希")}}async function ha(e){return await Up(e)}function $p(e,t,n=30){const r=new Date;r.setTime(r.getTime()+n*24*60*60*1e3);const l=`expires=${r.toUTCString()}`,i=window.location.protocol==="https:"?"; Secure":"",a=window.location.hostname,d=/^\d+\.\d+\.\d+\.\d+$/.test(a)?"":"; SameSite=Lax",g=`${e}=${t}; ${l}; path=/${d}${i}`;document.cookie=g}function Vp(e){const t=e+"=",n=document.cookie.split(";");for(let r=0;r<n.length;r++){let l=n[r];for(;l.charAt(0)===" ";)l=l.substring(1,l.length);if(l.indexOf(t)===0)return l.substring(t.length,l.length)}return console.log("[Cookie] 未找到Cookie:",{name:e,allCookies:document.cookie}),null}const Oc="webui_token",Bp=30;let Ln=null;function Hp(e){Ln=e}function Qp(){return Vp(Oc)}function ga(e){$p(Oc,e,Bp)}async function dt(e,t={}){const n=async r=>{const l={...t.headers};return r&&(l["x-webui-token"]=r),fetch(e,{...t,headers:l})};try{let r=await n(Qp());if(r.status===401&&Ln){console.log("401 - Password not set, prompting to set password...");const l=await Ln("请设置密码");if(!l||!l.trim())throw new Error("密码不能为空");if(!(await fetch("/api/set-token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:l.trim()})})).ok)throw new Error("设置密码失败");const i=await ha(l.trim());ga(i),r=await n(i)}if(r.status===403&&Ln){console.log("403 - Token verification failed, prompting for password...");let l=null;try{l=await r.clone().json()}catch{}l!=null&&l.locked&&ae(l.message||"账户已被锁定","error");let s=0;const i=5;for(;r.status===403&&s<i;)try{const a=s>0?"密码错误,请重新输入":"请输入密码",u=await Ln(a);if(!u||!u.trim())throw new Error("密码不能为空");const d=await ha(u.trim());if(ga(d),r=await n(d),r.status===200){console.log("Authentication successful!");break}try{if(l=await r.clone().json(),l!=null&&l.locked)throw new Error(l.message||"账户已被锁定")}catch{}s++}catch(a){throw console.error("Password prompt error:",a),a}if(r.status===403)throw new Error((l==null?void 0:l.message)||"认证失败")}if(!r.ok){const l=await r.text();throw new Error(`HTTP error! status: ${r.status}, message: ${l}`)}return await r.json()}catch(r){throw console.error("API fetch error:",r),r}}const Wp=({visible:e,onClose:t,onSuccess:n})=>{const[r,l]=C.useState(""),[s,i]=C.useState(""),[a,u]=C.useState(!1),[d,g]=C.useState(!1),[h,m]=C.useState(!1),[v,y]=C.useState(""),k=C.useRef(null);C.useEffect(()=>{e&&k.current&&setTimeout(()=>{var c;return(c=k.current)==null?void 0:c.focus()},100)},[e]),C.useEffect(()=>{e&&(l(""),i(""),u(!1),g(!1),y(""))},[e]);const w=async()=>{const c=Fc(r,6);if(!c.isValid){y(c.error||"密码验证失败");return}if(r!==s){y("两次输入的密码不一致");return}m(!0),y("");try{const p=await dt("/api/set-token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:r})});p.success?(ae("密码修改成功","success"),n(),t()):y(p.message||"密码修改失败")}catch(p){y(p.message||"密码修改失败")}finally{m(!1)}},f=c=>{c.key==="Enter"&&w()};return e?o.jsx(o.Fragment,{children:o.jsx("div",{className:"fixed inset-0 bg-black/30 backdrop-blur-sm flex items-center justify-center p-4",style:{zIndex:9e3},onClick:c=>c.target===c.currentTarget&&t(),children:o.jsxs("div",{className:"bg-white/90 backdrop-blur-xl rounded-3xl shadow-2xl w-full max-w-md transform transition-all",children:[o.jsxs("div",{className:"flex items-center gap-3 p-6 border-b border-white/20",children:[o.jsx("div",{className:"w-10 h-10 rounded-xl bg-gradient-to-br from-red-500 to-pink-600 flex items-center justify-center",children:o.jsx(Mc,{size:20,className:"text-white"})}),o.jsxs("div",{className:"flex-1",children:[o.jsx("h3",{className:"text-xl font-semibold text-gray-900",children:"修改 WebUI 密码"}),o.jsx("p",{className:"text-sm text-gray-600 mt-0.5",children:"请输入新密码"})]}),o.jsx("button",{onClick:t,className:"text-gray-400 hover:text-gray-600 transition-colors",children:o.jsx(sr,{size:24})})]}),o.jsxs("div",{className:"p-6 space-y-4",children:[v&&o.jsx("div",{className:"p-3 bg-red-50 border border-red-200 rounded-xl text-red-600 text-sm",children:v}),o.jsxs("div",{children:[o.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-2",children:"新密码"}),o.jsxs("div",{className:"relative",children:[o.jsx("input",{ref:k,type:a?"text":"password",value:r,onChange:c=>{l(c.target.value),y("")},onKeyPress:f,placeholder:"请输入新密码(支持数字、字母、符号)",className:"w-full px-4 py-3 pr-12 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all bg-white/50 backdrop-blur-sm",autoComplete:"new-password"}),o.jsx("button",{type:"button",onClick:()=>u(!a),className:"absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors",children:a?o.jsx(hn,{size:20}):o.jsx(gn,{size:20})})]}),o.jsx("p",{className:"text-xs text-gray-500 mt-1",children:"密码长度至少6位"})]}),o.jsxs("div",{children:[o.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-2",children:"确认密码"}),o.jsxs("div",{className:"relative",children:[o.jsx("input",{type:d?"text":"password",value:s,onChange:c=>{i(c.target.value),y("")},onKeyPress:f,placeholder:"请再次输入新密码",className:"w-full px-4 py-3 pr-12 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all bg-white/50 backdrop-blur-sm",autoComplete:"new-password"}),o.jsx("button",{type:"button",onClick:()=>g(!d),className:"absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors",children:d?o.jsx(hn,{size:20}):o.jsx(gn,{size:20})})]})]})]}),o.jsxs("div",{className:"flex items-center justify-end gap-3 p-6 border-t border-white/20",children:[o.jsx("button",{onClick:t,disabled:h,className:"px-6 py-2.5 text-gray-700 hover:bg-gray-100 rounded-lg font-medium transition-colors disabled:opacity-50",children:"取消"}),o.jsx("button",{onClick:w,disabled:h||!r.trim()||!s.trim(),className:"px-6 py-2.5 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg font-medium hover:shadow-lg transition-all disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:shadow-none",children:h?"修改中...":"确定修改"})]})]})})}):null},Kp=({onLoginSuccess:e})=>{const[t,n]=C.useState("quick"),[r,l]=C.useState(!1),[s,i]=C.useState(!1),[a,u]=C.useState(!1),[d,g]=C.useState(""),[h,m]=C.useState([]),[v,y]=C.useState(null),[k,w]=C.useState(!1),f=C.useRef(null),c=C.useRef(null),p=C.useRef(null),x=C.useRef(!1),N={scanning:"扫描成功,请在手机上确认",success:"登录成功",expired:"二维码已过期,请刷新",error:"登录失败,请重试","":""},E=C.useCallback(()=>{x.current=!1,p.current&&(clearTimeout(p.current),p.current=null)},[]),z=C.useCallback(async()=>{if(x.current)return;x.current=!0,console.log("开始轮询登录状态...");const I=60;let oe=0;const P=async()=>{if(oe>=I){E(),ae("登录超时,请重试","error"),t==="qr"&&g("error");return}oe++;try{const R=await dt("/api/login-info");if(R.success&&R.data.online===!0){E(),ae("登录成功!正在跳转到主页面...","success"),t==="qr"&&g("success"),setTimeout(()=>{e()},1e3);return}p.current=setTimeout(P,3e3)}catch(R){console.warn("轮询登录状态失败:",R),p.current=setTimeout(P,3e3)}};await P()},[t,e,E]),_=C.useCallback(I=>{if(!f.current)return;const P=f.current.getContext("2d");if(!P)return;const R=new Image;R.onload=()=>{P.clearRect(0,0,200,200),P.drawImage(R,0,0,200,200)},R.src=I},[]),F=C.useCallback(async()=>{if(f.current)try{const I=await dt("/api/login-qrcode");if(I.success&&I.data){_(I.data.pngBase64QrcodeData);const oe=I.data.expireTime*1e3;c.current&&clearInterval(c.current),c.current=setTimeout(()=>{u(!0),g("expired"),E()},oe),u(!1),g(""),ae("请使用手机QQ扫码登录","warning"),await z()}else throw new Error(I.message||"获取二维码失败")}catch(I){ae(I.message||"获取二维码失败","error"),console.error("QR code generation error:",I)}},[_,z,E]),b=C.useCallback(async()=>{await F(),ae("二维码已刷新","success")},[F]),L=C.useRef(!1),M=C.useCallback(async()=>{if(!L.current){L.current=!0;try{const I=await dt("/api/quick-login-list");if(console.log("Quick login list response:",I),I.success&&I.data&&I.data.LocalLoginInfoList){const oe=I.data.LocalLoginInfoList.filter(P=>P.isQuickLogin&&!P.isUserLogin);m(oe),console.log("Accounts loaded:",oe),oe.length>0?y(P=>P??oe[0]):n("qr")}else console.warn("No quick login accounts available:",I.message),m([])}catch(I){console.error("Failed to fetch quick login list:",I),ae("获取快速登录列表失败","error"),m([])}}},[]),S=C.useCallback(async()=>{if(v){i(!0);try{const oe=(await dt("/api/quick-login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({uin:v.uin})})).data;if(oe.result==="0")ae(`正在登录 ${v.nickName}...`,"success"),await z();else throw new Error(oe.loginErrorInfo.errMsg||"登录失败")}catch(I){ae(I.message,"error"),console.error("Quick login error:",I),n("qr")}finally{i(!1)}}},[v,z]),O=()=>{l(!r)},X=I=>{y(I),l(!1)};return C.useEffect(()=>(L.current||M(),()=>{c.current&&clearInterval(c.current),E()}),[]),C.useEffect(()=>{t==="qr"?setTimeout(()=>F(),100):c.current&&clearInterval(c.current),t==="quick"&&h.length===0&&!L.current&&M()},[t,h.length,F]),o.jsx("div",{className:"relative min-h-screen flex flex-col items-center justify-center p-5",children:o.jsxs("div",{className:"bg-white/50 backdrop-blur-2xl rounded-3xl p-10 shadow-xl border border-white/30 min-w-[320px] text-center relative z-10",children:[t==="quick"&&o.jsxs("div",{className:"flex flex-col items-center gap-6",children:[!r&&v&&o.jsxs("div",{className:"flex flex-col items-center cursor-pointer p-4 rounded-2xl transition-colors hover:bg-blue-50",onClick:O,children:[o.jsx("div",{className:"w-20 h-20 rounded-full overflow-hidden mb-3 shadow-lg",children:o.jsx("img",{src:v.faceUrl,alt:v.nickName,className:"w-full h-full object-cover"})}),o.jsx("div",{className:"text-base text-gray-800 mb-2",children:v.nickName})]}),r&&o.jsx("div",{className:"grid grid-cols-2 gap-4 my-5 w-full max-w-md",children:h.map(I=>o.jsxs("div",{className:"flex flex-col items-center p-4 rounded-2xl cursor-pointer transition-all border-2 border-transparent hover:bg-blue-50 hover:border-blue-500",onClick:()=>X(I),children:[o.jsx("div",{className:"w-[60px] h-[60px] rounded-full overflow-hidden mb-2 shadow-md",children:o.jsx("img",{src:I.faceUrl,alt:I.nickName,className:"w-full h-full object-cover"})}),o.jsx("div",{className:"text-sm text-gray-800 text-center truncate w-full px-1",children:I.nickName})]},I.uin))}),!r&&o.jsx("button",{onClick:S,disabled:!v||s,className:"w-[280px] h-11 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-full font-medium text-base disabled:opacity-50 disabled:cursor-not-allowed hover:shadow-lg transition-all flex items-center justify-center gap-2",children:s?o.jsxs(o.Fragment,{children:[o.jsx(Vt,{size:20,className:"animate-spin"}),"登录中..."]}):"登录"}),o.jsxs("div",{className:"flex gap-6 justify-center",children:[!r&&o.jsx("button",{onClick:O,className:"text-blue-600 text-sm hover:underline",children:"切换账号"}),o.jsx("button",{onClick:()=>n("qr"),className:"text-blue-600 text-sm hover:underline",children:"扫码登录"})]})]}),t==="qr"&&o.jsxs("div",{className:"flex flex-col items-center gap-5",children:[o.jsx("div",{className:"relative inline-block",children:o.jsxs("div",{className:"relative p-5 bg-white rounded-2xl shadow-lg",children:[o.jsx("canvas",{ref:f,width:"200",height:"200",className:"block rounded-lg"}),a&&o.jsxs("div",{className:"absolute inset-0 bg-black/70 flex flex-col items-center justify-center text-white cursor-pointer rounded-2xl transition-opacity hover:opacity-90",onClick:b,children:[o.jsx(Pp,{size:32,className:"mb-2"}),o.jsx("div",{children:"点击刷新"})]})]})}),o.jsx("div",{className:"text-gray-600",children:"请使用手机QQ扫码登录"}),d&&o.jsx("div",{className:`text-sm px-4 py-2 rounded-lg ${d==="success"?"bg-green-100 text-green-800":d==="error"||d==="expired"?"bg-red-100 text-red-800":"bg-blue-100 text-blue-800"}`,children:N[d]})]}),o.jsx("div",{className:"mt-6",children:t==="qr"&&h.length>0&&o.jsx("button",{onClick:()=>n("quick"),className:"text-blue-600 text-sm hover:underline",children:"快速登录"})})]})})},qp=!1,Gp=()=>({friendCount:128,groupCount:45,messageReceived:12580,messageSent:3842,startupTime:Math.floor(Date.now()/1e3)-3600*5-1234,lastMessageTime:Math.floor(Date.now()/1e3)-30,bot:{memory:(80+Math.random()*40)*1024*1024,totalMemory:16*1024*1024*1024,memoryPercent:2+Math.random()*3,cpu:3+Math.random()*10},qq:{memory:(200+Math.random()*100)*1024*1024,totalMemory:16*1024*1024*1024,memoryPercent:5+Math.random()*8,cpu:5+Math.random()*15}}),ya=e=>!e||e<=0?"0 MB":e<1024?e+" B":e<1024*1024?(e/1024).toFixed(1)+" KB":e<1024*1024*1024?(e/1024/1024).toFixed(0)+" MB":(e/1024/1024/1024).toFixed(2)+" GB",Yp=e=>{const n=Math.floor(Date.now()/1e3)-e,r=Math.floor(n/86400),l=Math.floor(n%86400/3600),s=Math.floor(n%3600/60),i=n%60;return r>0?`${r}天 ${l}时 ${s}分`:l>0?`${l}时 ${s}分 ${i}秒`:s>0?`${s}分 ${i}秒`:`${i}秒`},Xp=e=>e?new Date(e*1e3).toLocaleString("zh-CN"):"暂无",_r=({icon:e,label:t,value:n,gradient:r})=>o.jsxs("div",{className:"flex items-center gap-3 p-3 rounded-xl bg-white/30 hover:bg-white/50 transition-all duration-200 hover:scale-[1.02]",children:[o.jsx("div",{className:`w-10 h-10 rounded-xl ${r} flex items-center justify-center shadow-md`,children:e}),o.jsxs("div",{className:"flex-1 min-w-0",children:[o.jsx("p",{className:"text-xs text-gray-500",children:t}),o.jsx("p",{className:"text-lg font-bold text-gray-800 truncate",children:n})]})]}),xa=({value:e,size:t=100,strokeWidth:n=8,gradientId:r,gradientColors:l,label:s,displayValue:i,icon:a})=>{const u=(t-n)/2,d=u*2*Math.PI,g=Math.min(Math.max(e,0),100),h=d-g/100*d;return o.jsxs("div",{className:"flex flex-col items-center",children:[o.jsxs("div",{className:"relative",style:{width:t,height:t},children:[o.jsxs("svg",{width:t,height:t,className:"transform -rotate-90",children:[o.jsx("defs",{children:o.jsxs("linearGradient",{id:r,x1:"0%",y1:"0%",x2:"100%",y2:"100%",children:[o.jsx("stop",{offset:"0%",stopColor:l[0]}),o.jsx("stop",{offset:"100%",stopColor:l[1]})]})}),o.jsx("circle",{cx:t/2,cy:t/2,r:u,fill:"none",stroke:"rgba(0,0,0,0.06)",strokeWidth:n}),o.jsx("circle",{cx:t/2,cy:t/2,r:u,fill:"none",stroke:`url(#${r})`,strokeWidth:n,strokeDasharray:d,strokeDashoffset:h,strokeLinecap:"round",className:"transition-all duration-1000 ease-out"})]}),o.jsxs("div",{className:"absolute inset-0 flex flex-col items-center justify-center",children:[o.jsx("div",{className:"w-8 h-8 rounded-lg flex items-center justify-center shadow-md",style:{background:`linear-gradient(135deg, ${l[0]}, ${l[1]})`},children:a}),o.jsxs("span",{className:"text-sm font-bold text-gray-800 mt-1",children:[g.toFixed(1),"%"]})]})]}),o.jsx("p",{className:"text-xs font-semibold text-gray-700 mt-2",children:s}),o.jsx("p",{className:"text-xs text-gray-500",children:i})]})},va=({title:e,icon:t,gradient:n,cpu:r,memory:l,totalMemory:s,memoryPercent:i,cpuGradientId:a,memGradientId:u,cpuColors:d,memColors:g})=>o.jsxs("div",{className:"card p-4",children:[o.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[o.jsx("div",{className:`w-8 h-8 rounded-lg ${n} flex items-center justify-center shadow-md`,children:t}),o.jsx("h4",{className:"text-sm font-semibold text-gray-800",children:e})]}),o.jsxs("div",{className:"flex justify-around",children:[o.jsx(xa,{value:r,gradientId:a,gradientColors:d,label:"CPU",displayValue:`${r.toFixed(1)}%`,icon:o.jsx(Lc,{size:16,className:"text-white"})}),o.jsx(xa,{value:i,gradientId:u,gradientColors:g,label:"内存",displayValue:`${ya(l)} / ${ya(s)}`,icon:o.jsx(xp,{size:16,className:"text-white"})})]})]}),Zp=()=>{const[e,t]=C.useState(null),[n,r]=C.useState(!0),[l,s]=C.useState(""),i=C.useRef(),a=async()=>{try{const u=qp?Gp():(await dt("/api/dashboard/stats")).data;u&&t(u)}catch(u){console.error("Failed to fetch dashboard stats:",u)}finally{r(!1)}};return C.useEffect(()=>(a(),i.current=window.setInterval(a,5e3),()=>{i.current&&clearInterval(i.current)}),[]),C.useEffect(()=>{if(!(e!=null&&e.startupTime))return;const u=()=>s(Yp(e.startupTime));u();const d=setInterval(u,1e3);return()=>clearInterval(d)},[e==null?void 0:e.startupTime]),n?o.jsx("div",{className:"flex items-center justify-center h-64",children:o.jsx("div",{className:"w-12 h-12 border-4 border-blue-500 border-t-transparent rounded-full animate-spin"})}):e?o.jsxs("div",{className:"space-y-5",children:[o.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-4",children:[o.jsxs("div",{className:"card p-4 flex flex-col",children:[o.jsxs("div",{className:"flex items-center gap-3 mb-3",children:[o.jsx("div",{className:"w-10 h-10 rounded-xl bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center shadow-md",children:o.jsx(Br,{size:20,className:"text-white"})}),o.jsx("h3",{className:"text-base font-semibold text-gray-800",children:"运行时间"}),o.jsxs("div",{className:"ml-auto flex items-center gap-1 px-2 py-0.5 rounded-full bg-green-100 text-green-600 text-xs font-medium",children:[o.jsx(Mp,{size:12}),"运行中"]})]}),o.jsxs("div",{className:"flex-1 flex flex-col justify-center space-y-2",children:[o.jsxs("div",{className:"p-3 rounded-xl bg-gradient-to-r from-indigo-50 to-purple-50",children:[o.jsx("p",{className:"text-xs text-gray-500",children:"已运行"}),o.jsx("p",{className:"text-xl font-bold bg-gradient-to-r from-indigo-600 to-purple-600 bg-clip-text text-transparent",children:l})]}),o.jsxs("div",{className:"px-3 py-2",children:[o.jsx("p",{className:"text-xs text-gray-500",children:"启动时间"}),o.jsx("p",{className:"text-sm font-medium text-gray-700",children:Xp(e.startupTime)})]})]})]}),o.jsxs("div",{className:"card p-4 space-y-3",children:[o.jsx(_r,{icon:o.jsx(Tp,{size:20,className:"text-white"}),label:"好友数量",value:e.friendCount.toLocaleString(),gradient:"bg-gradient-to-br from-blue-500 to-cyan-500"}),o.jsx(_r,{icon:o.jsx(_p,{size:20,className:"text-white"}),label:"群组数量",value:e.groupCount.toLocaleString(),gradient:"bg-gradient-to-br from-purple-500 to-pink-500"})]}),o.jsxs("div",{className:"card p-4 space-y-3",children:[o.jsx(_r,{icon:o.jsx(jp,{size:20,className:"text-white"}),label:"收到消息",value:e.messageReceived.toLocaleString(),gradient:"bg-gradient-to-br from-green-500 to-emerald-500"}),o.jsx(_r,{icon:o.jsx(lo,{size:20,className:"text-white"}),label:"发送消息",value:e.messageSent.toLocaleString(),gradient:"bg-gradient-to-br from-orange-500 to-amber-500"})]})]}),o.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[o.jsx(va,{title:"QQ 资源",icon:o.jsx(wp,{size:16,className:"text-white"}),gradient:"bg-gradient-to-br from-blue-500 to-cyan-500",cpu:e.qq.cpu,memory:e.qq.memory,totalMemory:e.qq.totalMemory,memoryPercent:e.qq.memoryPercent,cpuGradientId:"qqCpuGradient",memGradientId:"qqMemGradient",cpuColors:["#3b82f6","#06b6d4"],memColors:["#0ea5e9","#22d3ee"]}),o.jsx(va,{title:"Bot 资源",icon:o.jsx(hp,{size:16,className:"text-white"}),gradient:"bg-gradient-to-br from-violet-500 to-purple-600",cpu:e.bot.cpu,memory:e.bot.memory,totalMemory:e.bot.totalMemory,memoryPercent:e.bot.memoryPercent,cpuGradientId:"botCpuGradient",memGradientId:"botMemGradient",cpuColors:["#8b5cf6","#a855f7"],memColors:["#6366f1","#8b5cf6"]})]})]}):o.jsx("div",{className:"card p-8 text-center",children:o.jsx("p",{className:"text-gray-500",children:"无法加载统计数据"})})},us=()=>{const e=C.useRef(null),t=C.useRef([]),n=C.useRef(),r=C.useRef(0);return C.useEffect(()=>{const l=e.current;if(!l)return;const s=l.getContext("2d",{alpha:!0});if(!s)return;const a=1e3/30,u=()=>{l.width=window.innerWidth,l.height=window.innerHeight,t.current.forEach(y=>{y.offscreenCanvas=g(y)})},d=["rgba(139, 92, 246, 0.6)","rgba(59, 130, 246, 0.6)","rgba(236, 72, 153, 0.6)","rgba(16, 185, 129, 0.6)","rgba(245, 158, 11, 0.6)","rgba(168, 85, 247, 0.6)","rgba(14, 165, 233, 0.6)","rgba(251, 113, 133, 0.6)"],g=y=>{const k=Math.ceil(y.baseRadius*2.5),w=document.createElement("canvas");w.width=k,w.height=k;const f=w.getContext("2d");if(!f)return w;const c=k/2,p=k/2,x=y.baseRadius,N=f.createRadialGradient(c,p,0,c,p,x);return N.addColorStop(0,y.color.replace("0.6","0.8")),N.addColorStop(.5,y.color),N.addColorStop(1,y.color.replace("0.6","0")),f.fillStyle=N,f.beginPath(),f.arc(c,p,x,0,Math.PI*2),f.fill(),w},h=()=>{const y=[];for(let w=0;w<8;w++){const f=Math.random()*80+60,c={x:Math.random()*l.width,y:Math.random()*l.height,vx:(Math.random()-.5)*.8,vy:(Math.random()-.5)*.8,radius:f,baseRadius:f,scale:1,scaleSpeed:Math.random()*.002+.001,color:d[Math.floor(Math.random()*d.length)]};c.offscreenCanvas=g(c),y.push(c)}t.current=y},m=(y,k)=>{const w=k.x-y.x,f=k.y-y.y,c=Math.sqrt(w*w+f*f);if(c<y.radius+k.radius){const p=Math.atan2(f,w),x=Math.sin(p),N=Math.cos(p),E=y.vx*N+y.vy*x,z=y.vy*N-y.vx*x,_=k.vx*N+k.vy*x,F=k.vy*N-k.vx*x;y.vx=_*N-z*x,y.vy=z*N+_*x,k.vx=E*N-F*x,k.vy=F*N+E*x;const b=(y.radius+k.radius-c)/2;y.x-=b*N,y.y-=b*x,k.x+=b*N,k.y+=b*x}},v=y=>{n.current=requestAnimationFrame(v);const k=y-r.current;k<a||(r.current=y-k%a,s.clearRect(0,0,l.width,l.height),t.current.forEach((w,f)=>{w.x+=w.vx,w.y+=w.vy,w.scale+=w.scaleSpeed,(w.scale>1.2||w.scale<.8)&&(w.scaleSpeed=-w.scaleSpeed),w.radius=w.baseRadius*w.scale,(w.x-w.radius<0||w.x+w.radius>l.width)&&(w.vx=-w.vx,w.x=Math.max(w.radius,Math.min(l.width-w.radius,w.x))),(w.y-w.radius<0||w.y+w.radius>l.height)&&(w.vy=-w.vy,w.y=Math.max(w.radius,Math.min(l.height-w.radius,w.y)));for(let c=f+1;c<t.current.length;c++)m(w,t.current[c]);if(w.offscreenCanvas){const c=w.offscreenCanvas.width*w.scale;s.drawImage(w.offscreenCanvas,w.x-c/2,w.y-c/2,c,c)}}))};return u(),window.addEventListener("resize",u),h(),n.current=requestAnimationFrame(v),()=>{window.removeEventListener("resize",u),n.current&&cancelAnimationFrame(n.current)}},[]),o.jsx("canvas",{ref:e,className:"fixed inset-0 w-full h-full pointer-events-none",style:{zIndex:0}})},Jp={enable:!0,connect:[]},e0={enable:!1,port:5600,token:""},t0={enable:!1,reportSelfMessage:!1,http:{port:3010,prefix:"",accessToken:""},webhook:{urls:[]}},n0={enable:!0,port:3080},r0={webui:n0,onlyLocalhost:!0,milky:t0,satori:e0,ob11:Jp,enableLocalFile2Url:!1,log:!0,autoDeleteFile:!1,autoDeleteFileSecond:60,musicSignUrl:"https://llob.linyuchen.net/sign/music",msgCacheExpire:120,ffmpeg:"",rawMsgPB:!1},l0="7.1.2";function s0(){const[e,t]=C.useState("dashboard"),[n,r]=C.useState(r0),[l,s]=C.useState(!1),[i,a]=C.useState(!1),[u,d]=C.useState(!0),[g,h]=C.useState(null),[m,v]=C.useState(!1),[y,k]=C.useState(""),[w,f]=C.useState(null),[c,p]=C.useState(!1),[x,N]=C.useState(!1),[E,z]=C.useState(!1);C.useEffect(()=>{Hp(async L=>new Promise(M=>{k(L||""),v(!0),f(()=>M)}))},[]);const _=C.useCallback(L=>{L.trim()?(v(!1),k(""),w&&(w(L),f(null))):k("密码不能为空")},[w]);C.useEffect(()=>{(async()=>{try{const M=await dt("/api/config");M.success&&M.data.selfInfo.online?(a(!0),h({nick:M.data.selfInfo.nick||"",uin:M.data.selfInfo.uin}),r(M.data.config)):a(!1)}catch(M){console.error("Failed to check login status:",M),a(!1)}finally{d(!1)}})()},[]);const F=C.useCallback(async L=>{try{s(!0);const S=await dt("/api/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({config:L||n})});S.success?ae("配置保存成功","success"):ae("保存失败:"+S.message,"error")}catch(M){ae("保存失败:"+M.message,"error")}finally{s(!1)}},[n]),b=C.useCallback(()=>{window.location.reload()},[]);return u?o.jsxs(o.Fragment,{children:[o.jsx(us,{}),o.jsx("div",{className:"relative flex items-center justify-center min-h-screen z-10",children:o.jsx(Vt,{size:48,className:"animate-spin text-blue-500"})}),o.jsx(as,{visible:m,onConfirm:_,error:y})]}):i?o.jsxs("div",{className:"flex min-h-screen",children:[o.jsx(us,{}),o.jsx(Rp,{activeTab:e,onTabChange:t,accountInfo:g||void 0}),o.jsx("main",{className:"flex-1 p-8 overflow-auto z-10",children:o.jsxs("div",{className:"max-w-6xl mx-auto",children:[o.jsxs("div",{className:"mb-8",children:[o.jsx("h2",{className:"text-3xl font-bold text-white mb-2",children:e==="dashboard"&&"Dashboard"}),o.jsx("p",{className:"text-white/80",children:e==="dashboard"&&"欢迎使用 Lucky Lillia Bot"})]}),e==="dashboard"&&o.jsx(Zp,{}),e==="onebot"&&o.jsx(Op,{config:n.ob11,globalConfig:n,onChange:L=>{const M={...n,ob11:L};r(M)},onSave:L=>{if(L){const M={...n,ob11:L};F(M)}else F()}}),e==="satori"&&o.jsxs("div",{className:"card p-6",children:[o.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[o.jsx("div",{className:"w-12 h-12 rounded-xl bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center",children:o.jsx(so,{size:24,className:"text-white"})}),o.jsxs("div",{children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"Satori 协议"}),o.jsx("p",{className:"text-sm text-gray-600",children:"配置 Satori 协议相关设置"})]})]}),o.jsxs("div",{className:"space-y-4",children:[o.jsxs("div",{className:"flex items-center justify-between p-4 bg-gray-50/50 rounded-xl hover:bg-gray-100/50 transition-colors",children:[o.jsxs("div",{children:[o.jsx("div",{className:"text-sm font-medium text-gray-800",children:"启用 Satori 协议"}),o.jsx("div",{className:"text-xs text-gray-500 mt-0.5",children:"开启后将支持 Satori 协议连接"})]}),o.jsx("input",{type:"checkbox",checked:n.satori.enable,onChange:L=>r({...n,satori:{...n.satori,enable:L.target.checked}}),className:`w-12 h-6 rounded-full bg-gray-300 relative cursor-pointer appearance-none\r
|
|
291
291
|
checked:bg-gradient-to-r checked:from-blue-500 checked:to-purple-600\r
|
|
292
292
|
transition-colors duration-200 ease-in-out\r
|
|
293
293
|
before:content-[''] before:absolute before:top-0.5 before:left-0.5\r
|
package/webui/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>WebUI</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-B8SmuMJC.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-CO7Tbtyt.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|