llonebot-dist 6.6.7 → 6.6.9

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":"6.6.7","type":"module","description":"","main":"llonebot.js","author":"linyuchen"}
1
+ {"name":"llonebot-dist","version":"6.6.9","type":"module","description":"","main":"llonebot.js","author":"linyuchen"}
@@ -247,7 +247,7 @@ Error generating stack: `+s.message+`
247
247
  before:content-[''] before:absolute before:top-0.5 before:left-0.5\r
248
248
  before:w-5 before:h-5 before:rounded-full before:bg-white\r
249
249
  before:transition-transform before:duration-200\r
250
- 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(ls,{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(ls,{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(ls,{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(ia,{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(ia,{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(xp,{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(Pc,{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(hp,{size:16}),"修改密码"]})]})]})]})};function Lc(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 ss=({visible:e,onConfirm:t,onClose:n,error:r})=>{const[l,s]=E.useState(""),[i,a]=E.useState(!1),[u,f]=E.useState(""),p=E.useRef(null);E.useEffect(()=>{e&&p.current&&setTimeout(()=>{var y;return(y=p.current)==null?void 0:y.focus()},100)},[e]),E.useEffect(()=>{e&&(s(""),a(!1),f(""))},[e]);const g=()=>{const y=Lc(l);if(!y.isValid){f(y.error||"密码验证失败");return}f(""),t(l.trim())},h=y=>{y.key==="Enter"&&g()};return E.useEffect(()=>{if(!e)return;const y=x=>{x.key==="Escape"&&(x.preventDefault(),x.stopPropagation())};return window.addEventListener("keydown",y),()=>window.removeEventListener("keydown",y)},[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:y=>y.target===y.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:p,type:i?"text":"password",value:l,onChange:y=>{s(y.target.value),u&&f("")},onKeyPress:h,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(rr,{size:20}):o.jsx(lr,{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:g,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 Pp(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,f=3144134277,p=1013904242,g=2773480762,h=1359893119,y=2600822924,x=528734635,k=1541459225;for(let M=0;M<s;M+=64){const d=new Uint32Array(64);for(let N=0;N<16;N++)d[N]=a.getUint32(M+N*4,!1);for(let N=16;N<64;N++){const U=(d[N-15]>>>7|d[N-15]<<25)^(d[N-15]>>>18|d[N-15]<<14)^d[N-15]>>>3,$=(d[N-2]>>>17|d[N-2]<<15)^(d[N-2]>>>19|d[N-2]<<13)^d[N-2]>>>10;d[N]=d[N-16]+U+d[N-7]+$>>>0}let c=u,m=f,v=p,C=g,j=h,z=y,_=x,T=k;for(let N=0;N<64;N++){const U=(j>>>6|j<<26)^(j>>>11|j<<21)^(j>>>25|j<<7),$=j&z^~j&_,S=T+U+$+t[N]+d[N]>>>0,D=(c>>>2|c<<30)^(c>>>13|c<<19)^(c>>>22|c<<10),ee=c&m^c&v^m&v,I=D+ee>>>0;T=_,_=z,z=j,j=C+S>>>0,C=v,v=m,m=c,c=S+I>>>0}u=u+c>>>0,f=f+m>>>0,p=p+v>>>0,g=g+C>>>0,h=h+j>>>0,y=y+z>>>0,x=x+_>>>0,k=k+T>>>0}return[u.toString(16).padStart(8,"0"),f.toString(16).padStart(8,"0"),p.toString(16).padStart(8,"0"),g.toString(16).padStart(8,"0"),h.toString(16).padStart(8,"0"),y.toString(16).padStart(8,"0"),x.toString(16).padStart(8,"0"),k.toString(16).padStart(8,"0")].join("")}async function zp(e){try{return Pp(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 pa(e){return await zp(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,f=/^\d+\.\d+\.\d+\.\d+$/.test(a)?"":"; SameSite=Lax",p=`${e}=${t}; ${l}; path=/${f}${i}`;document.cookie=p}function Lp(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 Tc="webui_token",Tp=30;let Ln=null;function Mp(e){Ln=e}function Rp(){return Lp(Tc)}function ma(e){_p(Tc,e,Tp)}async function Tt(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(Rp());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 pa(l.trim());ma(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&&he(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 f=await pa(u.trim());if(ma(f),r=await n(f),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 Ip=({visible:e,onClose:t,onSuccess:n})=>{const[r,l]=E.useState(""),[s,i]=E.useState(""),[a,u]=E.useState(!1),[f,p]=E.useState(!1),[g,h]=E.useState(!1),[y,x]=E.useState(""),k=E.useRef(null);E.useEffect(()=>{e&&k.current&&setTimeout(()=>{var c;return(c=k.current)==null?void 0:c.focus()},100)},[e]),E.useEffect(()=>{e&&(l(""),i(""),u(!1),p(!1),x(""))},[e]);const M=async()=>{const c=Lc(r,6);if(!c.isValid){x(c.error||"密码验证失败");return}if(r!==s){x("两次输入的密码不一致");return}h(!0),x("");try{const m=await Tt("/api/set-token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:r})});m.success?(he("密码修改成功","success"),n(),t()):x(m.message||"密码修改失败")}catch(m){x(m.message||"密码修改失败")}finally{h(!1)}},d=c=>{c.key==="Enter"&&M()};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(Pc,{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:[y&&o.jsx("div",{className:"p-3 bg-red-50 border border-red-200 rounded-xl text-red-600 text-sm",children:y}),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),x("")},onKeyPress:d,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(rr,{size:20}):o.jsx(lr,{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:f?"text":"password",value:s,onChange:c=>{i(c.target.value),x("")},onKeyPress:d,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:()=>p(!f),className:"absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors",children:f?o.jsx(rr,{size:20}):o.jsx(lr,{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:g,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:M,disabled:g||!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:g?"修改中...":"确定修改"})]})]})})}):null},bp=({onLoginSuccess:e})=>{const[t,n]=E.useState("quick"),[r,l]=E.useState(!1),[s,i]=E.useState(!1),[a,u]=E.useState(!1),[f,p]=E.useState(""),[g,h]=E.useState([]),[y,x]=E.useState(null),[k,M]=E.useState(!1),d=E.useRef(null),c=E.useRef(null),m=E.useRef(null),v=E.useRef(!1),C={scanning:"扫描成功,请在手机上确认",success:"登录成功",expired:"二维码已过期,请刷新",error:"登录失败,请重试","":""},j=E.useCallback(()=>{v.current=!1,m.current&&(clearTimeout(m.current),m.current=null)},[]),z=E.useCallback(async()=>{if(v.current)return;v.current=!0,console.log("开始轮询登录状态...");const I=60;let oe=0;const P=async()=>{if(oe>=I){j(),he("登录超时,请重试","error"),t==="qr"&&p("error");return}oe++;try{const R=await Tt("/api/login-info");if(R.success&&R.data.online===!0){j(),he("登录成功!正在跳转到主页面...","success"),t==="qr"&&p("success"),setTimeout(()=>{e()},1e3);return}m.current=setTimeout(P,3e3)}catch(R){console.warn("轮询登录状态失败:",R),m.current=setTimeout(P,3e3)}};await P()},[t,e,j]),_=E.useCallback(I=>{if(!d.current)return;const P=d.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},[]),T=E.useCallback(async()=>{if(d.current)try{const I=await Tt("/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),p("expired"),j()},oe),u(!1),p(""),he("请使用手机QQ扫码登录","warning"),await z()}else throw new Error(I.message||"获取二维码失败")}catch(I){he(I.message||"获取二维码失败","error"),console.error("QR code generation error:",I)}},[_,z,j]),N=E.useCallback(async()=>{await T(),he("二维码已刷新","success")},[T]),U=E.useRef(!1),$=E.useCallback(async()=>{if(!U.current){U.current=!0;try{const I=await Tt("/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);h(oe),console.log("Accounts loaded:",oe),oe.length>0?x(P=>P??oe[0]):n("qr")}else console.warn("No quick login accounts available:",I.message),h([])}catch(I){console.error("Failed to fetch quick login list:",I),he("获取快速登录列表失败","error"),h([])}}},[]),S=E.useCallback(async()=>{if(y){i(!0);try{const oe=(await Tt("/api/quick-login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({uin:y.uin})})).data;if(oe.result==="0")he(`正在登录 ${y.nickName}...`,"success"),await z();else throw new Error(oe.loginErrorInfo.errMsg||"登录失败")}catch(I){he(I.message,"error"),console.error("Quick login error:",I),n("qr")}finally{i(!1)}}},[y,z]),D=()=>{l(!r)},ee=I=>{x(I),l(!1)};return E.useEffect(()=>(U.current||$(),()=>{c.current&&clearInterval(c.current),j()}),[]),E.useEffect(()=>{t==="qr"?setTimeout(()=>T(),100):c.current&&clearInterval(c.current),t==="quick"&&g.length===0&&!U.current&&$()},[t,g.length,T]),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&&y&&o.jsxs("div",{className:"flex flex-col items-center cursor-pointer p-4 rounded-2xl transition-colors hover:bg-blue-50",onClick:D,children:[o.jsx("div",{className:"w-20 h-20 rounded-full overflow-hidden mb-3 shadow-lg",children:o.jsx("img",{src:y.faceUrl,alt:y.nickName,className:"w-full h-full object-cover"})}),o.jsx("div",{className:"text-base text-gray-800 mb-2",children:y.nickName})]}),r&&o.jsx("div",{className:"grid grid-cols-2 gap-4 my-5 w-full max-w-md",children:g.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:()=>ee(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:!y||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(_n,{size:20,className:"animate-spin"}),"登录中..."]}):"登录"}),o.jsxs("div",{className:"flex gap-6 justify-center",children:[!r&&o.jsx("button",{onClick:D,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:d,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:N,children:[o.jsx(vp,{size:32,className:"mb-2"}),o.jsx("div",{children:"点击刷新"})]})]})}),o.jsx("div",{className:"text-gray-600",children:"请使用手机QQ扫码登录"}),f&&o.jsx("div",{className:`text-sm px-4 py-2 rounded-lg ${f==="success"?"bg-green-100 text-green-800":f==="error"||f==="expired"?"bg-red-100 text-red-800":"bg-blue-100 text-blue-800"}`,children:C[f]})]}),o.jsx("div",{className:"mt-6",children:t==="qr"&&g.length>0&&o.jsx("button",{onClick:()=>n("quick"),className:"text-blue-600 text-sm hover:underline",children:"快速登录"})})]})})},os=()=>{const e=E.useRef(null),t=E.useRef([]),n=E.useRef();return E.useEffect(()=>{const r=e.current;if(!r)return;const l=r.getContext("2d");if(!l)return;const s=()=>{r.width=window.innerWidth,r.height=window.innerHeight};s(),window.addEventListener("resize",s);const i=["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)"];(()=>{const p=[];for(let h=0;h<8;h++){const y=Math.random()*80+60;p.push({x:Math.random()*r.width,y:Math.random()*r.height,vx:(Math.random()-.5)*.8,vy:(Math.random()-.5)*.8,radius:y,baseRadius:y,scale:1,scaleSpeed:Math.random()*.002+.001,color:i[Math.floor(Math.random()*i.length)]})}t.current=p})();const u=(p,g)=>{const h=g.x-p.x,y=g.y-p.y,x=Math.sqrt(h*h+y*y);if(x<p.radius+g.radius){const k=Math.atan2(y,h),M=Math.sin(k),d=Math.cos(k),c=p.vx*d+p.vy*M,m=p.vy*d-p.vx*M,v=g.vx*d+g.vy*M,C=g.vy*d-g.vx*M;p.vx=v*d-m*M,p.vy=m*d+v*M,g.vx=c*d-C*M,g.vy=C*d+c*M;const j=(p.radius+g.radius-x)/2;p.x-=j*d,p.y-=j*M,g.x+=j*d,g.y+=j*M}},f=()=>{l.clearRect(0,0,r.width,r.height),t.current.forEach((p,g)=>{p.x+=p.vx,p.y+=p.vy,p.scale+=p.scaleSpeed,(p.scale>1.2||p.scale<.8)&&(p.scaleSpeed=-p.scaleSpeed),p.radius=p.baseRadius*p.scale,(p.x-p.radius<0||p.x+p.radius>r.width)&&(p.vx=-p.vx,p.x=Math.max(p.radius,Math.min(r.width-p.radius,p.x))),(p.y-p.radius<0||p.y+p.radius>r.height)&&(p.vy=-p.vy,p.y=Math.max(p.radius,Math.min(r.height-p.radius,p.y)));for(let y=g+1;y<t.current.length;y++)u(p,t.current[y]);const h=l.createRadialGradient(p.x,p.y,0,p.x,p.y,p.radius);h.addColorStop(0,p.color.replace("0.6","0.8")),h.addColorStop(.5,p.color),h.addColorStop(1,p.color.replace("0.6","0")),l.fillStyle=h,l.beginPath(),l.arc(p.x,p.y,p.radius,0,Math.PI*2),l.fill(),l.filter="blur(20px)",l.fill(),l.filter="none"}),n.current=requestAnimationFrame(f)};return f(),()=>{window.removeEventListener("resize",s),n.current&&cancelAnimationFrame(n.current)}},[]),o.jsx("canvas",{ref:e,className:"fixed inset-0 w-full h-full pointer-events-none",style:{zIndex:0}})},Op={enable:!0,connect:[]},Fp={enable:!1,port:5600,token:""},Dp={enable:!0,port:3080},Ap={webui:Dp,onlyLocalhost:!0,satori:Fp,ob11:Op,enableLocalFile2Url:!1,log:!0,autoDeleteFile:!1,autoDeleteFileSecond:60,musicSignUrl:"https://llob.linyuchen.net/sign/music",msgCacheExpire:120,ffmpeg:"",rawMsgPB:!1},Up="6.6.6";function $p(){const[e,t]=E.useState("dashboard"),[n,r]=E.useState(Ap),[l,s]=E.useState(!1),[i,a]=E.useState(!1),[u,f]=E.useState(!0),[p,g]=E.useState(null),[h,y]=E.useState(!1),[x,k]=E.useState(""),[M,d]=E.useState(null),[c,m]=E.useState(!1),[v,C]=E.useState(!1);E.useEffect(()=>{Mp(async T=>new Promise(N=>{k(T||""),y(!0),d(()=>N)}))},[]);const j=E.useCallback(T=>{T.trim()?(y(!1),k(""),M&&(M(T),d(null))):k("密码不能为空")},[M]);E.useEffect(()=>{(async()=>{try{const N=await Tt("/api/config");N.success&&N.data.selfInfo.online?(a(!0),g({nick:N.data.selfInfo.nick||"",uin:N.data.selfInfo.uin}),r(N.data.config)):a(!1)}catch(N){console.error("Failed to check login status:",N),a(!1)}finally{f(!1)}})()},[]);const z=E.useCallback(async T=>{try{s(!0);const U=await Tt("/api/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({config:T||n})});U.success?he("配置保存成功","success"):he("保存失败:"+U.message,"error")}catch(N){he("保存失败:"+N.message,"error")}finally{s(!1)}},[n]),_=E.useCallback(()=>{window.location.reload()},[]);return u?o.jsxs(o.Fragment,{children:[o.jsx(os,{}),o.jsx("div",{className:"relative flex items-center justify-center min-h-screen z-10",children:o.jsx(_n,{size:48,className:"animate-spin text-blue-500"})}),o.jsx(ss,{visible:h,onConfirm:j,error:x})]}):i?o.jsxs("div",{className:"flex min-h-screen",children:[o.jsx(os,{}),o.jsx(jp,{activeTab:e,onTabChange:t,accountInfo:p||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"&&"欢迎使用 LLTwoBot"})]}),e==="dashboard"&&o.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6",children:[o.jsxs("div",{className:"card p-6 hover:scale-105",children:[o.jsxs("div",{className:"flex items-center justify-between mb-4",children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"OneBot 11"}),o.jsx("span",{className:`px-3 py-1 rounded-full text-xs font-medium ${n.ob11.enable?"bg-green-100 text-green-800":"bg-gray-100 text-gray-800"}`,children:n.ob11.enable?"已启用":"未启用"})]}),o.jsx("p",{className:"text-sm text-gray-600",children:"OneBot 11 协议配置"}),o.jsx("button",{onClick:()=>t("onebot"),className:"mt-4 text-blue-600 text-sm font-medium hover:text-blue-700",children:"前往配置 →"})]}),o.jsxs("div",{className:"card p-6 hover:scale-105",children:[o.jsxs("div",{className:"flex items-center justify-between mb-4",children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"Satori"}),o.jsx("span",{className:`px-3 py-1 rounded-full text-xs font-medium ${n.satori.enable?"bg-green-100 text-green-800":"bg-gray-100 text-gray-800"}`,children:n.satori.enable?"已启用":"未启用"})]}),o.jsx("p",{className:"text-sm text-gray-600",children:"Satori 协议配置"}),o.jsx("button",{onClick:()=>t("satori"),className:"mt-4 text-blue-600 text-sm font-medium hover:text-blue-700",children:"前往配置 →"})]}),o.jsxs("div",{className:"card p-6 hover:scale-105",children:[o.jsxs("div",{className:"flex items-center justify-between mb-4",children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"系统设置"}),o.jsx("span",{className:"px-3 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800",children:"配置"})]}),o.jsx("p",{className:"text-sm text-gray-600",children:"全局配置和系统选项"}),o.jsx("button",{onClick:()=>t("other"),className:"mt-4 text-blue-600 text-sm font-medium hover:text-blue-700",children:"前往配置 →"})]})]}),e==="onebot"&&o.jsx(Cp,{config:n.ob11,globalConfig:n,onChange:T=>{const N={...n,ob11:T};r(N)},onSave:T=>{if(T){const N={...n,ob11:T};z(N)}else z()}}),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(zc,{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:T=>r({...n,satori:{...n.satori,enable:T.target.checked}}),className:`w-12 h-6 rounded-full bg-gray-300 relative cursor-pointer appearance-none\r
250
+ 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(ls,{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(ls,{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(ls,{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(ia,{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(ia,{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(xp,{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(Pc,{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(hp,{size:16}),"修改密码"]})]})]})]})};function Lc(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 ss=({visible:e,onConfirm:t,onClose:n,error:r})=>{const[l,s]=E.useState(""),[i,a]=E.useState(!1),[u,f]=E.useState(""),p=E.useRef(null);E.useEffect(()=>{e&&p.current&&setTimeout(()=>{var y;return(y=p.current)==null?void 0:y.focus()},100)},[e]),E.useEffect(()=>{e&&(s(""),a(!1),f(""))},[e]);const g=()=>{const y=Lc(l);if(!y.isValid){f(y.error||"密码验证失败");return}f(""),t(l.trim())},h=y=>{y.key==="Enter"&&g()};return E.useEffect(()=>{if(!e)return;const y=x=>{x.key==="Escape"&&(x.preventDefault(),x.stopPropagation())};return window.addEventListener("keydown",y),()=>window.removeEventListener("keydown",y)},[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:y=>y.target===y.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:p,type:i?"text":"password",value:l,onChange:y=>{s(y.target.value),u&&f("")},onKeyPress:h,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(rr,{size:20}):o.jsx(lr,{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:g,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 Pp(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,f=3144134277,p=1013904242,g=2773480762,h=1359893119,y=2600822924,x=528734635,k=1541459225;for(let M=0;M<s;M+=64){const d=new Uint32Array(64);for(let N=0;N<16;N++)d[N]=a.getUint32(M+N*4,!1);for(let N=16;N<64;N++){const U=(d[N-15]>>>7|d[N-15]<<25)^(d[N-15]>>>18|d[N-15]<<14)^d[N-15]>>>3,$=(d[N-2]>>>17|d[N-2]<<15)^(d[N-2]>>>19|d[N-2]<<13)^d[N-2]>>>10;d[N]=d[N-16]+U+d[N-7]+$>>>0}let c=u,m=f,v=p,C=g,j=h,z=y,_=x,T=k;for(let N=0;N<64;N++){const U=(j>>>6|j<<26)^(j>>>11|j<<21)^(j>>>25|j<<7),$=j&z^~j&_,S=T+U+$+t[N]+d[N]>>>0,D=(c>>>2|c<<30)^(c>>>13|c<<19)^(c>>>22|c<<10),ee=c&m^c&v^m&v,I=D+ee>>>0;T=_,_=z,z=j,j=C+S>>>0,C=v,v=m,m=c,c=S+I>>>0}u=u+c>>>0,f=f+m>>>0,p=p+v>>>0,g=g+C>>>0,h=h+j>>>0,y=y+z>>>0,x=x+_>>>0,k=k+T>>>0}return[u.toString(16).padStart(8,"0"),f.toString(16).padStart(8,"0"),p.toString(16).padStart(8,"0"),g.toString(16).padStart(8,"0"),h.toString(16).padStart(8,"0"),y.toString(16).padStart(8,"0"),x.toString(16).padStart(8,"0"),k.toString(16).padStart(8,"0")].join("")}async function zp(e){try{return Pp(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 pa(e){return await zp(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,f=/^\d+\.\d+\.\d+\.\d+$/.test(a)?"":"; SameSite=Lax",p=`${e}=${t}; ${l}; path=/${f}${i}`;document.cookie=p}function Lp(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 Tc="webui_token",Tp=30;let Ln=null;function Mp(e){Ln=e}function Rp(){return Lp(Tc)}function ma(e){_p(Tc,e,Tp)}async function Tt(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(Rp());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 pa(l.trim());ma(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&&he(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 f=await pa(u.trim());if(ma(f),r=await n(f),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 Ip=({visible:e,onClose:t,onSuccess:n})=>{const[r,l]=E.useState(""),[s,i]=E.useState(""),[a,u]=E.useState(!1),[f,p]=E.useState(!1),[g,h]=E.useState(!1),[y,x]=E.useState(""),k=E.useRef(null);E.useEffect(()=>{e&&k.current&&setTimeout(()=>{var c;return(c=k.current)==null?void 0:c.focus()},100)},[e]),E.useEffect(()=>{e&&(l(""),i(""),u(!1),p(!1),x(""))},[e]);const M=async()=>{const c=Lc(r,6);if(!c.isValid){x(c.error||"密码验证失败");return}if(r!==s){x("两次输入的密码不一致");return}h(!0),x("");try{const m=await Tt("/api/set-token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:r})});m.success?(he("密码修改成功","success"),n(),t()):x(m.message||"密码修改失败")}catch(m){x(m.message||"密码修改失败")}finally{h(!1)}},d=c=>{c.key==="Enter"&&M()};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(Pc,{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:[y&&o.jsx("div",{className:"p-3 bg-red-50 border border-red-200 rounded-xl text-red-600 text-sm",children:y}),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),x("")},onKeyPress:d,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(rr,{size:20}):o.jsx(lr,{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:f?"text":"password",value:s,onChange:c=>{i(c.target.value),x("")},onKeyPress:d,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:()=>p(!f),className:"absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors",children:f?o.jsx(rr,{size:20}):o.jsx(lr,{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:g,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:M,disabled:g||!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:g?"修改中...":"确定修改"})]})]})})}):null},bp=({onLoginSuccess:e})=>{const[t,n]=E.useState("quick"),[r,l]=E.useState(!1),[s,i]=E.useState(!1),[a,u]=E.useState(!1),[f,p]=E.useState(""),[g,h]=E.useState([]),[y,x]=E.useState(null),[k,M]=E.useState(!1),d=E.useRef(null),c=E.useRef(null),m=E.useRef(null),v=E.useRef(!1),C={scanning:"扫描成功,请在手机上确认",success:"登录成功",expired:"二维码已过期,请刷新",error:"登录失败,请重试","":""},j=E.useCallback(()=>{v.current=!1,m.current&&(clearTimeout(m.current),m.current=null)},[]),z=E.useCallback(async()=>{if(v.current)return;v.current=!0,console.log("开始轮询登录状态...");const I=60;let oe=0;const P=async()=>{if(oe>=I){j(),he("登录超时,请重试","error"),t==="qr"&&p("error");return}oe++;try{const R=await Tt("/api/login-info");if(R.success&&R.data.online===!0){j(),he("登录成功!正在跳转到主页面...","success"),t==="qr"&&p("success"),setTimeout(()=>{e()},1e3);return}m.current=setTimeout(P,3e3)}catch(R){console.warn("轮询登录状态失败:",R),m.current=setTimeout(P,3e3)}};await P()},[t,e,j]),_=E.useCallback(I=>{if(!d.current)return;const P=d.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},[]),T=E.useCallback(async()=>{if(d.current)try{const I=await Tt("/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),p("expired"),j()},oe),u(!1),p(""),he("请使用手机QQ扫码登录","warning"),await z()}else throw new Error(I.message||"获取二维码失败")}catch(I){he(I.message||"获取二维码失败","error"),console.error("QR code generation error:",I)}},[_,z,j]),N=E.useCallback(async()=>{await T(),he("二维码已刷新","success")},[T]),U=E.useRef(!1),$=E.useCallback(async()=>{if(!U.current){U.current=!0;try{const I=await Tt("/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);h(oe),console.log("Accounts loaded:",oe),oe.length>0?x(P=>P??oe[0]):n("qr")}else console.warn("No quick login accounts available:",I.message),h([])}catch(I){console.error("Failed to fetch quick login list:",I),he("获取快速登录列表失败","error"),h([])}}},[]),S=E.useCallback(async()=>{if(y){i(!0);try{const oe=(await Tt("/api/quick-login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({uin:y.uin})})).data;if(oe.result==="0")he(`正在登录 ${y.nickName}...`,"success"),await z();else throw new Error(oe.loginErrorInfo.errMsg||"登录失败")}catch(I){he(I.message,"error"),console.error("Quick login error:",I),n("qr")}finally{i(!1)}}},[y,z]),D=()=>{l(!r)},ee=I=>{x(I),l(!1)};return E.useEffect(()=>(U.current||$(),()=>{c.current&&clearInterval(c.current),j()}),[]),E.useEffect(()=>{t==="qr"?setTimeout(()=>T(),100):c.current&&clearInterval(c.current),t==="quick"&&g.length===0&&!U.current&&$()},[t,g.length,T]),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&&y&&o.jsxs("div",{className:"flex flex-col items-center cursor-pointer p-4 rounded-2xl transition-colors hover:bg-blue-50",onClick:D,children:[o.jsx("div",{className:"w-20 h-20 rounded-full overflow-hidden mb-3 shadow-lg",children:o.jsx("img",{src:y.faceUrl,alt:y.nickName,className:"w-full h-full object-cover"})}),o.jsx("div",{className:"text-base text-gray-800 mb-2",children:y.nickName})]}),r&&o.jsx("div",{className:"grid grid-cols-2 gap-4 my-5 w-full max-w-md",children:g.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:()=>ee(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:!y||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(_n,{size:20,className:"animate-spin"}),"登录中..."]}):"登录"}),o.jsxs("div",{className:"flex gap-6 justify-center",children:[!r&&o.jsx("button",{onClick:D,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:d,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:N,children:[o.jsx(vp,{size:32,className:"mb-2"}),o.jsx("div",{children:"点击刷新"})]})]})}),o.jsx("div",{className:"text-gray-600",children:"请使用手机QQ扫码登录"}),f&&o.jsx("div",{className:`text-sm px-4 py-2 rounded-lg ${f==="success"?"bg-green-100 text-green-800":f==="error"||f==="expired"?"bg-red-100 text-red-800":"bg-blue-100 text-blue-800"}`,children:C[f]})]}),o.jsx("div",{className:"mt-6",children:t==="qr"&&g.length>0&&o.jsx("button",{onClick:()=>n("quick"),className:"text-blue-600 text-sm hover:underline",children:"快速登录"})})]})})},os=()=>{const e=E.useRef(null),t=E.useRef([]),n=E.useRef();return E.useEffect(()=>{const r=e.current;if(!r)return;const l=r.getContext("2d");if(!l)return;const s=()=>{r.width=window.innerWidth,r.height=window.innerHeight};s(),window.addEventListener("resize",s);const i=["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)"];(()=>{const p=[];for(let h=0;h<8;h++){const y=Math.random()*80+60;p.push({x:Math.random()*r.width,y:Math.random()*r.height,vx:(Math.random()-.5)*.8,vy:(Math.random()-.5)*.8,radius:y,baseRadius:y,scale:1,scaleSpeed:Math.random()*.002+.001,color:i[Math.floor(Math.random()*i.length)]})}t.current=p})();const u=(p,g)=>{const h=g.x-p.x,y=g.y-p.y,x=Math.sqrt(h*h+y*y);if(x<p.radius+g.radius){const k=Math.atan2(y,h),M=Math.sin(k),d=Math.cos(k),c=p.vx*d+p.vy*M,m=p.vy*d-p.vx*M,v=g.vx*d+g.vy*M,C=g.vy*d-g.vx*M;p.vx=v*d-m*M,p.vy=m*d+v*M,g.vx=c*d-C*M,g.vy=C*d+c*M;const j=(p.radius+g.radius-x)/2;p.x-=j*d,p.y-=j*M,g.x+=j*d,g.y+=j*M}},f=()=>{l.clearRect(0,0,r.width,r.height),t.current.forEach((p,g)=>{p.x+=p.vx,p.y+=p.vy,p.scale+=p.scaleSpeed,(p.scale>1.2||p.scale<.8)&&(p.scaleSpeed=-p.scaleSpeed),p.radius=p.baseRadius*p.scale,(p.x-p.radius<0||p.x+p.radius>r.width)&&(p.vx=-p.vx,p.x=Math.max(p.radius,Math.min(r.width-p.radius,p.x))),(p.y-p.radius<0||p.y+p.radius>r.height)&&(p.vy=-p.vy,p.y=Math.max(p.radius,Math.min(r.height-p.radius,p.y)));for(let y=g+1;y<t.current.length;y++)u(p,t.current[y]);const h=l.createRadialGradient(p.x,p.y,0,p.x,p.y,p.radius);h.addColorStop(0,p.color.replace("0.6","0.8")),h.addColorStop(.5,p.color),h.addColorStop(1,p.color.replace("0.6","0")),l.fillStyle=h,l.beginPath(),l.arc(p.x,p.y,p.radius,0,Math.PI*2),l.fill(),l.filter="blur(20px)",l.fill(),l.filter="none"}),n.current=requestAnimationFrame(f)};return f(),()=>{window.removeEventListener("resize",s),n.current&&cancelAnimationFrame(n.current)}},[]),o.jsx("canvas",{ref:e,className:"fixed inset-0 w-full h-full pointer-events-none",style:{zIndex:0}})},Op={enable:!0,connect:[]},Fp={enable:!1,port:5600,token:""},Dp={enable:!0,port:3080},Ap={webui:Dp,onlyLocalhost:!0,satori:Fp,ob11:Op,enableLocalFile2Url:!1,log:!0,autoDeleteFile:!1,autoDeleteFileSecond:60,musicSignUrl:"https://llob.linyuchen.net/sign/music",msgCacheExpire:120,ffmpeg:"",rawMsgPB:!1},Up="6.6.9";function $p(){const[e,t]=E.useState("dashboard"),[n,r]=E.useState(Ap),[l,s]=E.useState(!1),[i,a]=E.useState(!1),[u,f]=E.useState(!0),[p,g]=E.useState(null),[h,y]=E.useState(!1),[x,k]=E.useState(""),[M,d]=E.useState(null),[c,m]=E.useState(!1),[v,C]=E.useState(!1);E.useEffect(()=>{Mp(async T=>new Promise(N=>{k(T||""),y(!0),d(()=>N)}))},[]);const j=E.useCallback(T=>{T.trim()?(y(!1),k(""),M&&(M(T),d(null))):k("密码不能为空")},[M]);E.useEffect(()=>{(async()=>{try{const N=await Tt("/api/config");N.success&&N.data.selfInfo.online?(a(!0),g({nick:N.data.selfInfo.nick||"",uin:N.data.selfInfo.uin}),r(N.data.config)):a(!1)}catch(N){console.error("Failed to check login status:",N),a(!1)}finally{f(!1)}})()},[]);const z=E.useCallback(async T=>{try{s(!0);const U=await Tt("/api/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({config:T||n})});U.success?he("配置保存成功","success"):he("保存失败:"+U.message,"error")}catch(N){he("保存失败:"+N.message,"error")}finally{s(!1)}},[n]),_=E.useCallback(()=>{window.location.reload()},[]);return u?o.jsxs(o.Fragment,{children:[o.jsx(os,{}),o.jsx("div",{className:"relative flex items-center justify-center min-h-screen z-10",children:o.jsx(_n,{size:48,className:"animate-spin text-blue-500"})}),o.jsx(ss,{visible:h,onConfirm:j,error:x})]}):i?o.jsxs("div",{className:"flex min-h-screen",children:[o.jsx(os,{}),o.jsx(jp,{activeTab:e,onTabChange:t,accountInfo:p||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"&&"欢迎使用 LLTwoBot"})]}),e==="dashboard"&&o.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6",children:[o.jsxs("div",{className:"card p-6 hover:scale-105",children:[o.jsxs("div",{className:"flex items-center justify-between mb-4",children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"OneBot 11"}),o.jsx("span",{className:`px-3 py-1 rounded-full text-xs font-medium ${n.ob11.enable?"bg-green-100 text-green-800":"bg-gray-100 text-gray-800"}`,children:n.ob11.enable?"已启用":"未启用"})]}),o.jsx("p",{className:"text-sm text-gray-600",children:"OneBot 11 协议配置"}),o.jsx("button",{onClick:()=>t("onebot"),className:"mt-4 text-blue-600 text-sm font-medium hover:text-blue-700",children:"前往配置 →"})]}),o.jsxs("div",{className:"card p-6 hover:scale-105",children:[o.jsxs("div",{className:"flex items-center justify-between mb-4",children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"Satori"}),o.jsx("span",{className:`px-3 py-1 rounded-full text-xs font-medium ${n.satori.enable?"bg-green-100 text-green-800":"bg-gray-100 text-gray-800"}`,children:n.satori.enable?"已启用":"未启用"})]}),o.jsx("p",{className:"text-sm text-gray-600",children:"Satori 协议配置"}),o.jsx("button",{onClick:()=>t("satori"),className:"mt-4 text-blue-600 text-sm font-medium hover:text-blue-700",children:"前往配置 →"})]}),o.jsxs("div",{className:"card p-6 hover:scale-105",children:[o.jsxs("div",{className:"flex items-center justify-between mb-4",children:[o.jsx("h3",{className:"text-lg font-semibold text-gray-800",children:"系统设置"}),o.jsx("span",{className:"px-3 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800",children:"配置"})]}),o.jsx("p",{className:"text-sm text-gray-600",children:"全局配置和系统选项"}),o.jsx("button",{onClick:()=>t("other"),className:"mt-4 text-blue-600 text-sm font-medium hover:text-blue-700",children:"前往配置 →"})]})]}),e==="onebot"&&o.jsx(Cp,{config:n.ob11,globalConfig:n,onChange:T=>{const N={...n,ob11:T};r(N)},onSave:T=>{if(T){const N={...n,ob11:T};z(N)}else z()}}),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(zc,{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:T=>r({...n,satori:{...n.satori,enable:T.target.checked}}),className:`w-12 h-6 rounded-full bg-gray-300 relative cursor-pointer appearance-none\r
251
251
  checked:bg-gradient-to-r checked:from-blue-500 checked:to-purple-600\r
252
252
  transition-colors duration-200 ease-in-out\r
253
253
  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-B9vGhdCO.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-DtjKEZ-N.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/index-DaqFU7JR.css">
9
9
  </head>
10
10
  <body>