Files
Nexus/web/app/assets/SettingsPage-FAHRRqSI.js
T
2026-07-08 22:31:31 +08:00

4 lines
38 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{_ as e,t}from"./VSelect-3h-EI23Y.js";import{n,t as r}from"./VRow-qjxp2VJ5.js";import{$ as i,$t as ee,Ar as a,Dr as o,Dt as s,Er as c,Et as te,L as l,Nr as ne,Or as u,Ot as re,Tr as d,Tt as f,Wr as p,Yr as m,_ as ie,_i as h,b as g,br as ae,g as oe,h as se,in as _,jr as v,kt as y,q as ce,qr as b,ri as x,u as le,ui as S,v as C,wr as w,xi as T,xr as E,y as D}from"./index-a0fi5f-0.js";import{t as O}from"./usePageActivateRefresh-BntaOABK.js";import{t as ue}from"./useSnackbar-u_XK4ZNm.js";import{i as k,n as A,o as j,t as M}from"./VCard-BwwttBcf.js";import{t as N}from"./VTextField-GUQr1tUN.js";import{t as de}from"./VDialog-BFQGuuXw.js";import{n as P,r as F,t as fe}from"./validation-BMzYTJL4.js";import{t as I}from"./VForm-CAvEgM-c.js";import{t as pe}from"./VSwitch-CIruBPax.js";import{t as me}from"./VTextarea-BMTWx02W.js";import{i as he,r as ge}from"./useTerminalQuickCommands-CGHoPHjs.js";var L={key:1,class:`text-medium-emphasis text-body-2 mb-4`},_e={class:`text-caption text-medium-emphasis mr-2`,style:{"min-width":`1.5rem`}},R={class:`d-flex flex-wrap ga-2`},ve=ne({__name:`TerminalQuickCommandsSettings`,setup(e){let t=ue(),{commands:n,loading:r,load:ee,create:s,update:te,remove:ne,reorder:re,customCommands:f,builtinCommands:_}=ge(),y=S(!1),w=S(null),O=S(``),P=S(``),F=S(!1),fe=S(!1),I=S(!1),pe=S(null),me=S(``);function ve(){w.value=null,O.value=``,P.value=``,y.value=!0}function ye(e){w.value=e.id,O.value=e.name,P.value=e.cmd.replace(/\r$/,``),y.value=!0}async function be(){if(!O.value.trim()||!P.value.trim()){t(`名称和命令不能为空`,`warning`);return}let e=P.value.trim();F.value=!0;try{w.value?await te(w.value,O.value,e):await s(O.value,e),y.value=!1,t(`已保存`)}catch(e){t(e instanceof Error?e.message:`保存失败`,`error`)}finally{F.value=!1}}function xe(e){pe.value=e.id,me.value=e.name,I.value=!0}async function Se(){if(pe.value){F.value=!0;try{await ne(pe.value),I.value=!1,t(`已删除`)}catch(e){t(e instanceof Error?e.message:`删除失败`,`error`)}finally{F.value=!1}}}async function Ce(e){let t=f();if(e<=0)return;let n=t.map(e=>e.id),r=n[e-1];n[e-1]=n[e],n[e]=r,await Te(n)}async function we(e){let t=f();if(e>=t.length-1)return;let n=t.map(e=>e.id),r=n[e+1];n[e+1]=n[e],n[e]=r,await Te(n)}async function Te(e){fe.value=!0;try{await re(e)}catch(e){t(e instanceof Error?e.message:`排序失败`,`error`)}finally{fe.value=!1}}return p(()=>{ee().catch(e=>t(e.message,`error`))}),(e,t)=>(b(),c(M,{id:`terminal-quick-commands`,elevation:`0`,border:``,rounded:`lg`,class:`mb-4`},{default:x(()=>[v(k,{class:`d-flex align-center flex-wrap ga-2`},{default:x(()=>[v(i,{class:`mr-1`},{default:x(()=>[...t[6]||=[a(`mdi-flash`,-1)]]),_:1}),t[8]||=a(` 终端快捷命令 `,-1),v(C),v(l,{size:`small`,color:`primary`,variant:`flat`,"prepend-icon":`mdi-plus`,onClick:ve},{default:x(()=>[...t[7]||=[a(` 添加命令 `,-1)]]),_:1})]),_:1}),v(D),v(A,null,{default:x(()=>[t[9]||=d(`div`,{class:`text-body-2 text-medium-emphasis mb-4`},` 自定义命令显示在终端栏最前(优先级最高)。终端页仅可点击执行;在此添加、编辑、删除与调整顺序。 `,-1),h(r)?(b(),c(ce,{key:0,indeterminate:``,color:`primary`,class:`mb-3`})):o(``,!0),h(f)().length===0&&!h(r)?(b(),u(`div`,L,` 暂无自定义命令,点击「添加命令」创建。 `)):o(``,!0),h(f)().length?(b(),c(le,{key:2,density:`compact`,class:`mb-4 pa-0`},{default:x(()=>[(b(!0),u(E,null,m(h(f)(),(e,t)=>(b(),c(se,{key:e.id,border:``,rounded:`lg`,class:`mb-2`},{prepend:x(()=>[d(`span`,_e,T(t+1),1)]),append:x(()=>[v(l,{icon:`mdi-arrow-up`,size:`x-small`,variant:`text`,disabled:t===0||fe.value,onClick:ae(e=>Ce(t),[`stop`])},null,8,[`disabled`,`onClick`]),v(l,{icon:`mdi-arrow-down`,size:`x-small`,variant:`text`,disabled:t===h(f)().length-1||fe.value,onClick:ae(e=>we(t),[`stop`])},null,8,[`disabled`,`onClick`]),v(l,{icon:`mdi-pencil`,size:`x-small`,variant:`text`,onClick:ae(t=>ye(e),[`stop`])},null,8,[`onClick`]),v(l,{icon:`mdi-delete`,size:`x-small`,variant:`text`,color:`error`,onClick:ae(t=>xe(e),[`stop`])},null,8,[`onClick`])]),default:x(()=>[v(oe,null,{default:x(()=>[a(T(e.name),1)]),_:2},1024),v(ie,{class:`font-mono text-truncate`},{default:x(()=>[a(T(e.cmd),1)]),_:2},1024)]),_:2},1024))),128))]),_:1})):o(``,!0),t[10]||=d(`div`,{class:`text-subtitle-2 mb-2`},`系统内置(不可编辑)`,-1),d(`div`,R,[(b(!0),u(E,null,m(h(_)(),e=>(b(),c(g,{key:e.id,size:`small`,variant:`outlined`,label:``},{default:x(()=>[a(T(e.name),1)]),_:2},1024))),128))])]),_:1}),v(de,{modelValue:y.value,"onUpdate:modelValue":t[3]||=e=>y.value=e,"max-width":`520`},{default:x(()=>[v(M,{border:``},{default:x(()=>[v(k,null,{default:x(()=>[a(T(w.value?`编辑命令`:`添加快捷命令`),1)]),_:1}),v(A,null,{default:x(()=>[v(N,{modelValue:O.value,"onUpdate:modelValue":t[0]||=e=>O.value=e,label:`显示名称`,variant:`outlined`,density:`compact`,class:`mb-3`},null,8,[`modelValue`]),t[11]||=d(`div`,{class:`text-body-2 text-medium-emphasis mb-2`},`命令内容(发送时自动追加回车)`,-1),v(he,{modelValue:P.value,"onUpdate:modelValue":t[1]||=e=>P.value=e,multiline:``,rows:4,placeholder:`systemctl status nginx`},null,8,[`modelValue`])]),_:1}),v(j,null,{default:x(()=>[v(C),v(l,{variant:`text`,onClick:t[2]||=e=>y.value=!1},{default:x(()=>[...t[12]||=[a(`取消`,-1)]]),_:1}),v(l,{color:`primary`,variant:`flat`,loading:F.value,onClick:be},{default:x(()=>[...t[13]||=[a(`保存`,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1})]),_:1},8,[`modelValue`]),v(de,{modelValue:I.value,"onUpdate:modelValue":t[5]||=e=>I.value=e,"max-width":`400`},{default:x(()=>[v(M,{border:``},{default:x(()=>[v(k,null,{default:x(()=>[...t[14]||=[a(`删除命令`,-1)]]),_:1}),v(A,null,{default:x(()=>[a(`确定删除「`+T(me.value)+`」?`,1)]),_:1}),v(j,null,{default:x(()=>[v(C),v(l,{variant:`text`,onClick:t[4]||=e=>I.value=!1},{default:x(()=>[...t[15]||=[a(`取消`,-1)]]),_:1}),v(l,{color:`error`,variant:`flat`,loading:F.value,onClick:Se},{default:x(()=>[...t[16]||=[a(`删除`,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1})]),_:1},8,[`modelValue`])]),_:1}))}}),ye=[{key:`notify_alert_cpu`,label:`CPU 超阈值告警`,desc:`CPU 超阈值或恢复时推送;关闭则该类告警与恢复均不通知`,group:`服务器资源`},{key:`notify_alert_mem`,label:`内存超阈值告警`,desc:`内存超阈值或恢复时推送;关闭则该类告警与恢复均不通知`,group:`服务器资源`},{key:`notify_alert_disk`,label:`磁盘超阈值告警`,desc:`磁盘超阈值或恢复时推送;关闭则该类告警与恢复均不通知`,group:`服务器资源`},{key:`notify_recovery`,label:`资源恢复正常`,desc:`CPU/内存/磁盘回落正常时推送(须总开关开启且对应资源开关未关)`,group:`服务器资源`},{key:`notify_alert_offline`,label:`子机离线告警`,desc:`Agent 心跳丢失、子机由在线变为离线时推送一次;可在下方配置专用 Telegram Bot`,group:`服务器`},{key:`notify_time_drift`,label:`时钟偏差严重 (≥60s)`,desc:`子机与主机时间偏差过大影响 TOTP/cron`,group:`服务器`},{key:`notify_system_redis`,label:`Redis 连接异常 / 恢复`,desc:`Redis 不可达或恢复时推送`,group:`系统`},{key:`notify_system_mysql`,label:`MySQL 连接异常 / 恢复`,desc:`MySQL 不可达或恢复时推送`,group:`系统`},{key:`notify_restart`,label:`Nexus 后端重启`,desc:`Python 服务崩溃重启成功/失败时推送`,group:`系统`},{key:`notify_script_complete`,label:`脚本执行完成`,desc:`脚本批量执行结束时推送汇总与看板链接(不含失败明细)`,group:`运维`}],be={class:`d-flex flex-wrap ga-2 mb-4`},xe={class:`text-caption text-medium-emphasis font-weight-medium mt-2 mb-1`},Se={class:`d-flex flex-wrap ga-2 mb-2`},Ce={class:`d-flex flex-wrap align-center ga-2 mb-3`},we={class:`d-flex flex-wrap ga-2`},Te={key:2,class:`text-caption text-medium-emphasis mt-2 mb-0`},Ee={class:`d-flex align-center mb-3`},De={key:0,class:`text-center mb-3`},Oe=[`src`],ke={key:0,class:`d-flex align-center justify-center ga-2 mt-2`},Ae={class:`text-caption pa-1 bg-grey-lighten-4 rounded`,style:{"user-select":`all`}},je={key:1},Me={key:1,class:`d-flex ga-2 align-center`},Ne={class:`d-flex align-center ga-2`},Pe={class:`d-flex flex-wrap ga-2 mb-3`},Fe={key:0,class:`mb-4`},Ie={class:`text-caption text-medium-emphasis mb-2`},Le={key:0},Re={class:`d-flex flex-wrap ga-1`},ze={key:1,class:`text-caption text-medium-emphasis mb-4`},Be={class:`text-caption text-medium-emphasis`},Ve={class:`text-body-2 mb-2`},He={class:`d-flex flex-wrap ga-1 mb-2`,style:{"max-height":`240px`,"overflow-y":`auto`}},Ue={key:0,class:`text-body-2 text-medium-emphasis`},z=ne({name:`SettingsPage`,__name:`SettingsPage`,setup(ne){let p=ue(),{saveToServer:ie,previewSound:oe}=te(),{saveToServer:he,previewSound:ge}=f(),L=ee(),_e=re,R=S(s),z=S(!1),B=S(s),V=S(!1),We=S(!1),H=S({system_name:``,system_title:``,cpu_alert_threshold:80,mem_alert_threshold:80,disk_alert_threshold:80,alert_streak_required:3,db_pool_size:10,db_max_overflow:20,telegram_bot_token:``,telegram_chat_id:``,telegram_offline_chat_id:``}),U=S(``),W=S(!1),G=S(``),K=S(!1),q=S(!1),Ge=S(!1),Ke=S(!1),qe=S(!1),Je=S(`default`),Ye=S(!1),Xe=S(null),Ze=S(!1),Qe=S(!1),J=S(!1),$e=S([]),Y=S(!1),et=S(!1),tt=S({}),nt=S(null),X=S(null),rt=S(!1),it=S(!1),at=w(()=>{let e={};for(let t of ye)e[t.group]||(e[t.group]=[]),e[t.group].push(t);return e});function ot(e){return{private:`私聊`,group:`群组`,supergroup:`群组`,channel:`频道`}[e]||e}function st(e){let t=String(e??`true`).trim().toLowerCase();return![`false`,`0`,`no`,`off`].includes(t)}let Z=S({current:``,new_pw:``,confirm:``,totp_code:``}),ct=S(!1),lt=S(``),ut=S(``),dt=S(``),ft=S(!1),pt=S(!1),mt=S(``),ht=S(``),gt=S(!1),Q=S(!1),_t=S(``),vt=S(!1),yt=S(!1),bt=S(!1),xt=S(``),St=S(``),$=S([]),Ct=S(null),wt=S(0),Tt=S(!1),Et=S(!1),Dt=S(!1),Ot=S([]),kt=w(()=>$.value.slice(0,24));async function At(e=!1){e||(We.value=!0);try{let e=await _.get(`/settings/`),t=Array.isArray(e)?e:[],n=Object.keys(H.value);for(let e of t){let t=e.key;if(t===`telegram_bot_token`){W.value=!!e.value_set,U.value=``;continue}if(t===`telegram_offline_bot_token`){K.value=!!e.value_set,G.value=``;continue}if(t===`script_exec_complete_sound`){R.value=y(e.value);continue}if(t===`push_complete_sound`){B.value=y(e.value);continue}if(t&&ye.some(e=>e.key===t)){tt.value[t]=st(e.value);continue}if(t&&n.includes(t)){let n=e.value;typeof n==`string`&&/^\d+(\.\d+)?$/.test(n)?H.value[t]=Number(n):H.value[t]=n}}}catch{p(`加载设置失败`,`error`)}finally{e||(We.value=!1)}}async function jt(){try{let e=await _.get(`/settings/ip-allowlist`);bt.value=e.enabled||!1,xt.value=e.subscription_url||``,St.value=(e.manual_ips||[]).join(`
`),$.value=e.subscription_ips||[],Ct.value=e.last_refresh||null,wt.value=e.total_count??new Set([...e.manual_ips||[],...e.subscription_ips||[]]).size}catch{p(`加载白名单失败`,`error`)}}async function Mt(){let e=Xe.value;if(e){let{valid:t}=await e.validate();if(!t)return}Ye.value=!0;try{let e=Object.entries(H.value).filter(([e])=>[`system_name`,`system_title`,`cpu_alert_threshold`,`mem_alert_threshold`,`disk_alert_threshold`,`alert_streak_required`,`db_pool_size`,`db_max_overflow`].includes(e));for(let[t,n]of e)await _.put(`/settings/${t}`,{value:String(n??``)});p(`设置已保存`)}catch(e){p(e instanceof Error?e.message:`保存失败`,`error`)}finally{Ye.value=!1}}async function Nt(e){let t=U.value.trim(),n=String(H.value.telegram_chat_id||``).trim();return e?.requireToken&&!t&&!W.value?(p(`请先填写 Bot Token`,`error`),!1):e?.requireChatId&&!n?(p(`请先填写或检测 Chat ID`,`error`),!1):(t&&(await _.put(`/settings/telegram_bot_token`,{value:t}),W.value=!0,U.value=``,Y.value=!1),n&&await _.put(`/settings/telegram_chat_id`,{value:n}),!0)}async function Pt(e=!1){e||(rt.value=!0);try{X.value=await _.get(`/settings/ops-patrol/status`)}catch{X.value=null}finally{e||(rt.value=!1)}}async function Ft(){it.value=!0;try{if(!await Nt({requireToken:!0,requireChatId:!0}))return;let e=await _.post(`/settings/ops-patrol/sync-telegram`,{});X.value={...X.value||{},telegram_layer3_ready:e.telegram_layer3_ready,telegram_env_synced:e.env_status.env_synced,env_status:e.env_status,telegram_app_configured:!0},p(`巡检 Telegram 已同步至 .env`),await Pt()}catch(e){p(e instanceof Error?e.message:`同步失败`,`error`)}finally{it.value=!1}}async function It(){et.value=!0;try{let e=U.value.trim(),t=String(H.value.telegram_chat_id||``).trim();if(!e&&!t&&!W.value){p(`请先填写 Bot Token 或 Chat ID`,`warning`);return}await Nt(),await Pt(),p(`Telegram 配置已保存`)}catch(e){p(e instanceof Error?e.message:`保存失败`,`error`)}finally{et.value=!1}}async function Lt(e){let t=G.value.trim(),n=String(H.value.telegram_offline_chat_id||``).trim();return e?.requireToken&&!t&&!K.value?(p(`请先填写离线告警 Bot Token`,`error`),!1):e?.requireChatId&&!n?(p(`请先填写或检测离线告警 Chat ID`,`error`),!1):(t&&(await _.put(`/settings/telegram_offline_bot_token`,{value:t}),K.value=!0,G.value=``,q.value=!1),n&&await _.put(`/settings/telegram_offline_chat_id`,{value:n}),!0)}async function Rt(){Ge.value=!0;try{let e=G.value.trim(),t=String(H.value.telegram_offline_chat_id||``).trim();if(!e&&!t&&!K.value){p(`请先填写离线 Bot Token 或 Chat ID`,`warning`);return}await Lt(),p(`离线告警 Bot 已保存`)}catch(e){p(e instanceof Error?e.message:`保存失败`,`error`)}finally{Ge.value=!1}}async function zt(){Ke.value=!0;try{if(!await Lt({requireToken:!0,requireChatId:!0}))return;await _.post(`/settings/telegram/offline/test`),p(`离线通道测试消息已发送`)}catch(e){p(e instanceof Error?e.message:`发送失败`,`error`)}finally{Ke.value=!1}}async function Bt(){qe.value=!0;try{if(!await Lt({requireToken:!0}))return;if($e.value=(await _.get(`/settings/telegram/offline/chats`)).chats||[],!$e.value.length){p(`未检测到对话:私聊发消息,或群聊拉入 Bot 后发送 /start@Bot用户名`,`warning`);return}Je.value=`offline`,J.value=!0}catch(e){p(e instanceof Error?e.message:`检测失败`,`error`)}finally{qe.value=!1}}async function Vt(){if(q.value){q.value=!1,K.value&&(G.value=``);return}if(G.value.trim()){q.value=!0;return}if(!K.value){q.value=!0;return}yt.value=!0;try{G.value=(await _.post(`/settings/telegram/offline/reveal-token`,{})).value,q.value=!0}catch(e){p(e instanceof Error?e.message:`获取离线 Bot Token 失败`,`error`)}finally{yt.value=!1}}async function Ht(e){if(!e||z.value)return;let t=R.value;R.value=e,z.value=!0;try{await ie(e),p(`提示音设置已保存`)}catch(e){R.value=t,p(e instanceof Error?e.message:`保存失败`,`error`)}finally{z.value=!1}}function Ut(){oe(R.value)}async function Wt(e){if(!e||V.value)return;let t=B.value;B.value=e,V.value=!0;try{await he(e),p(`推送提示音设置已保存`)}catch(e){B.value=t,p(e instanceof Error?e.message:`保存失败`,`error`)}finally{V.value=!1}}function Gt(){ge(B.value)}async function Kt(e,t){let n=tt.value[e];tt.value[e]=t,nt.value=e;try{await _.put(`/settings/${e}`,{value:t?`true`:`false`})}catch(t){tt.value[e]=n,p(t instanceof Error?t.message:`保存失败,已撤销`,`error`)}finally{nt.value=null}}async function qt(){Ze.value=!0;try{if(!await Nt({requireToken:!0,requireChatId:!0}))return;await _.post(`/settings/telegram/test`),p(`测试消息已发送`)}catch(e){p(e instanceof Error?e.message:`发送失败`,`error`)}finally{Ze.value=!1}}async function Jt(){Qe.value=!0;try{if(!await Nt({requireToken:!0}))return;if($e.value=(await _.get(`/settings/telegram/chats`)).chats||[],!$e.value.length){p(`未检测到对话:私聊发消息,或群聊拉入 Bot 后发送 /start@Bot用户名`,`warning`);return}Je.value=`default`,J.value=!0}catch(e){p(e instanceof Error?e.message:`检测失败`,`error`)}finally{Qe.value=!1}}async function Yt(e){let t=String(e.id),n=Je.value===`offline`;n?H.value.telegram_offline_chat_id=t:H.value.telegram_chat_id=t,J.value=!1;try{let e=n?`telegram_offline_chat_id`:`telegram_chat_id`;await _.put(`/settings/${e}`,{value:t}),p(`已选择 Chat ID: ${t}`)}catch(e){p(e instanceof Error?e.message:`保存 Chat ID 失败`,`error`)}}async function Xt(){if(Z.value.new_pw!==Z.value.confirm){p(`两次密码不一致`,`error`);return}ct.value=!0;try{let e={current_password:Z.value.current,new_password:Z.value.new_pw};L.admin?.totp_enabled&&Z.value.totp_code&&(e.totp_code=Z.value.totp_code),await _.put(`/auth/password`,e),Z.value={current:``,new_pw:``,confirm:``,totp_code:``},p(`密码已修改`)}catch(e){p(e instanceof Error?e.message:`修改失败`,`error`)}finally{ct.value=!1}}async function Zt(){try{let e=await _.post(`/auth/totp/setup`);lt.value=e.qr_code,ut.value=e.secret||``}catch(e){p(e instanceof Error?e.message:`生成失败`,`error`)}}async function Qt(){ft.value=!0;try{await _.post(`/auth/totp/enable`,{code:dt.value}),await L.fetchProfile(),lt.value=``,dt.value=``,p(`TOTP 已启用`)}catch(e){p(e.message||`启用失败`,`error`)}finally{ft.value=!1}}function $t(){pt.value=!0}async function en(){gt.value=!0;try{await _.post(`/auth/totp/disable`,{admin_id:L.admin?.id,current_password:mt.value,totp_code:ht.value}),await L.fetchProfile(),pt.value=!1,mt.value=``,ht.value=``,p(`TOTP 已禁用`)}catch(e){p(e.message||`禁用失败`,`error`)}finally{gt.value=!1}}function tn(){ut.value&&(navigator.clipboard.writeText(ut.value),p(`密钥已复制`))}async function nn(){if(Q.value){Q.value=!1;return}vt.value=!0;try{_t.value=(await _.post(`/settings/api-key/reveal`,{})).value,Q.value=!0}catch(e){p(e instanceof Error?e.message:`获取 API Key 失败`,`error`)}finally{vt.value=!1}}async function rn(){if(Y.value){Y.value=!1,W.value&&(U.value=``);return}if(U.value.trim()){Y.value=!0;return}if(!W.value){Y.value=!0;return}yt.value=!0;try{U.value=(await _.post(`/settings/telegram/reveal-token`,{})).value,Y.value=!0}catch(e){p(e instanceof Error?e.message:`获取 Bot Token 失败`,`error`)}finally{yt.value=!1}}function an(){if(!Q.value||!_t.value){p(`请先点击眼睛图标显示 API Key`,`warning`);return}navigator.clipboard.writeText(_t.value),p(`已复制到剪贴板`)}async function on(){try{await _.post(`/settings/ip-allowlist/toggle?enabled=${bt.value?`true`:`false`}`)}catch(e){p(e instanceof Error?e.message:`操作失败`,`error`)}}async function sn(){let e=xt.value.trim();if(!e){p(`请先填写订阅 URL`,`error`);return}Et.value=!0;try{if(Ot.value=(await _.post(`/settings/ip-allowlist/parse-subscription`,{url:e})).hosts||[],!Ot.value.length){p(`未能解析出任何节点`,`warning`);return}Dt.value=!0}catch(e){p(e instanceof Error?e.message:`解析失败`,`error`)}finally{Et.value=!1}}async function cn(){Tt.value=!0;try{let e=St.value.split(`
`).map(e=>e.trim()).filter(Boolean),t={manual_ips:e,subscription_url:xt.value.trim(),enabled:bt.value},n=await _.post(`/settings/ip-allowlist`,t);n.refresh_ok===!1&&n.refresh_error?(p(`白名单已保存,但订阅刷新失败:${n.refresh_error}`,`warning`),await jt(!0)):($.value=n.subscription_ips||[],Ct.value=n.last_refresh||null,wt.value=new Set([...n.subscription_ips||[],...e]).size,p(`白名单已保存`)),Dt.value=!1}catch(e){p(e instanceof Error?e.message:`保存失败`,`error`)}finally{Tt.value=!1}}async function ln(e=!1){await Promise.all([At(e),jt(),Pt(e),L.fetchProfile()])}return O(e=>ln(e)),(ee,s)=>(b(),c(e,{fluid:``,class:`pa-6`},{default:x(()=>[v(r,null,{default:x(()=>[v(n,{cols:`12`,lg:`6`},{default:x(()=>[v(M,{elevation:`0`,border:``,rounded:`lg`,class:`mb-4`},{default:x(()=>[v(k,{class:`d-flex align-center`},{default:x(()=>[v(i,{class:`mr-2`},{default:x(()=>[...s[31]||=[a(`mdi-cog`,-1)]]),_:1}),s[32]||=a(` 系统设置 `,-1)]),_:1}),We.value?(b(),c(ce,{key:0,indeterminate:``,color:`primary`})):o(``,!0),v(D),v(I,{ref_key:`systemSettingsFormRef`,ref:Xe,onSubmit:ae(Mt,[`prevent`])},{default:x(()=>[v(A,null,{default:x(()=>[v(N,{modelValue:H.value.system_name,"onUpdate:modelValue":s[0]||=e=>H.value.system_name=e,label:`系统名称`,variant:`outlined`,density:`compact`,class:`mb-3`,rules:[h(F)(`系统名称`)]},null,8,[`modelValue`,`rules`]),v(N,{modelValue:H.value.system_title,"onUpdate:modelValue":s[1]||=e=>H.value.system_title=e,label:`系统标题`,variant:`outlined`,density:`compact`,class:`mb-3`,rules:[h(F)(`系统标题`)]},null,8,[`modelValue`,`rules`]),v(D,{class:`my-4`}),s[33]||=d(`div`,{class:`text-subtitle-2 mb-3`},`告警阈值`,-1),v(r,{dense:``},{default:x(()=>[v(n,{cols:`4`},{default:x(()=>[v(N,{modelValue:H.value.cpu_alert_threshold,"onUpdate:modelValue":s[2]||=e=>H.value.cpu_alert_threshold=e,label:`CPU %`,variant:`outlined`,density:`compact`,type:`number`,rules:[h(F)(`阈值`),h(P)(1,100,`阈值`)]},null,8,[`modelValue`,`rules`])]),_:1}),v(n,{cols:`4`},{default:x(()=>[v(N,{modelValue:H.value.mem_alert_threshold,"onUpdate:modelValue":s[3]||=e=>H.value.mem_alert_threshold=e,label:`内存 %`,variant:`outlined`,density:`compact`,type:`number`,rules:[h(F)(`阈值`),h(P)(1,100,`阈值`)]},null,8,[`modelValue`,`rules`])]),_:1}),v(n,{cols:`4`},{default:x(()=>[v(N,{modelValue:H.value.disk_alert_threshold,"onUpdate:modelValue":s[4]||=e=>H.value.disk_alert_threshold=e,label:`磁盘 %`,variant:`outlined`,density:`compact`,type:`number`,rules:[h(F)(`阈值`),h(P)(1,100,`阈值`)]},null,8,[`modelValue`,`rules`])]),_:1})]),_:1}),v(N,{modelValue:H.value.alert_streak_required,"onUpdate:modelValue":s[5]||=e=>H.value.alert_streak_required=e,label:`连续超阈次数`,hint:`默认 3:常态 60s 心跳约 3 分钟才告警;设为 1 则立即告警`,"persistent-hint":``,variant:`outlined`,density:`compact`,type:`number`,class:`mt-3`,rules:[h(F)(`连续次数`),h(P)(1,20,`连续次数`)]},null,8,[`modelValue`,`rules`]),v(D,{class:`my-4`}),s[34]||=d(`div`,{class:`text-subtitle-2 mb-3`},`连接池`,-1),v(r,{dense:``},{default:x(()=>[v(n,{cols:`6`},{default:x(()=>[v(N,{modelValue:H.value.db_pool_size,"onUpdate:modelValue":s[6]||=e=>H.value.db_pool_size=e,label:`连接池大小`,variant:`outlined`,density:`compact`,type:`number`,rules:[h(F)(`连接池大小`),h(P)(1,1e3,`连接池大小`)]},null,8,[`modelValue`,`rules`])]),_:1}),v(n,{cols:`6`},{default:x(()=>[v(N,{modelValue:H.value.db_max_overflow,"onUpdate:modelValue":s[7]||=e=>H.value.db_max_overflow=e,label:`溢出连接数`,variant:`outlined`,density:`compact`,type:`number`,rules:[h(F)(`溢出连接数`),h(P)(1,1e3,`溢出连接数`)]},null,8,[`modelValue`,`rules`])]),_:1})]),_:1})]),_:1}),v(j,{class:`px-4 pb-4`},{default:x(()=>[v(C),v(l,{type:`submit`,color:`primary`,variant:`flat`,loading:Ye.value},{default:x(()=>[...s[35]||=[a(`保存设置`,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1},512)]),_:1}),v(ve),v(M,{elevation:`0`,border:``,rounded:`lg`,class:`mb-4`},{default:x(()=>[v(k,{class:`d-flex align-center`},{default:x(()=>[v(i,{class:`mr-2`},{default:x(()=>[...s[36]||=[a(`mdi-bell-ring-outline`,-1)]]),_:1}),s[37]||=a(` 界面提示 `,-1)]),_:1}),v(D),v(A,null,{default:x(()=>[s[40]||=d(`p`,{class:`text-caption text-medium-emphasis mb-3`},` 脚本批量执行全部结束时,在浏览器播放提示音(仅当前登录的管理员会话,与 Telegram 推送无关)。 `,-1),v(t,{modelValue:R.value,"onUpdate:modelValue":[s[8]||=e=>R.value=e,Ht],items:h(_e),"item-title":`title`,"item-value":`value`,label:`脚本执行完成提示音`,variant:`outlined`,density:`compact`,"hide-details":``,class:`mb-3`,loading:z.value,disabled:z.value},null,8,[`modelValue`,`items`,`loading`,`disabled`]),v(l,{size:`small`,variant:`tonal`,"prepend-icon":`mdi-volume-high`,disabled:R.value===`off`||z.value,onClick:Ut},{default:x(()=>[...s[38]||=[a(` 试听 `,-1)]]),_:1},8,[`disabled`]),v(D,{class:`my-4`}),s[41]||=d(`p`,{class:`text-caption text-medium-emphasis mb-3`},` 文件推送批次结束且至少一台成功时,在浏览器播放提示音(与脚本提示音独立配置)。 `,-1),v(t,{modelValue:B.value,"onUpdate:modelValue":[s[9]||=e=>B.value=e,Wt],items:h(_e),"item-title":`title`,"item-value":`value`,label:`文件推送完成提示音`,variant:`outlined`,density:`compact`,"hide-details":``,class:`mb-3`,loading:V.value,disabled:V.value},null,8,[`modelValue`,`items`,`loading`,`disabled`]),v(l,{size:`small`,variant:`tonal`,"prepend-icon":`mdi-volume-high`,disabled:B.value===`off`||V.value,onClick:Gt},{default:x(()=>[...s[39]||=[a(` 试听 `,-1)]]),_:1},8,[`disabled`])]),_:1})]),_:1}),v(M,{elevation:`0`,border:``,rounded:`lg`},{default:x(()=>[v(k,{class:`d-flex align-center`},{default:x(()=>[v(i,{class:`mr-2`},{default:x(()=>[...s[42]||=[a(`mdi-send`,-1)]]),_:1}),s[43]||=a(` Telegram 推送 `,-1)]),_:1}),v(D),v(A,null,{default:x(()=>[v(N,{modelValue:U.value,"onUpdate:modelValue":s[10]||=e=>U.value=e,label:`Bot Token`,variant:`outlined`,density:`compact`,class:`mb-3`,placeholder:W.value?`已配置(留空保持不变)`:`输入 Bot Token`,type:Y.value?`text`:`password`,"append-inner-icon":Y.value?`mdi-eye-off`:`mdi-eye`,"onClick:appendInner":rn},null,8,[`modelValue`,`placeholder`,`type`,`append-inner-icon`]),W.value&&!U.value?(b(),c(g,{key:0,size:`small`,color:`success`,variant:`tonal`,class:`mb-3`},{default:x(()=>[...s[44]||=[a(`Token 已配置`,-1)]]),_:1})):o(``,!0),v(N,{modelValue:H.value.telegram_chat_id,"onUpdate:modelValue":s[11]||=e=>H.value.telegram_chat_id=e,label:`Chat ID`,variant:`outlined`,density:`compact`,class:`mb-3`},null,8,[`modelValue`]),s[56]||=d(`p`,{class:`text-caption text-medium-emphasis mb-3`},[a(` 私聊:向 Bot 发送任意消息。群聊:将 Bot 拉入群后发送 `),d(`code`,null,`/start@你的Bot用户名`),a(`(或 @提及 Bot),再点击下方检测。 `)],-1),d(`div`,be,[v(l,{size:`small`,variant:`tonal`,"prepend-icon":`mdi-radar`,onClick:Jt,loading:Qe.value},{default:x(()=>[...s[45]||=[a(`检测 Chat ID`,-1)]]),_:1},8,[`loading`]),v(l,{size:`small`,variant:`tonal`,"prepend-icon":`mdi-message-text`,onClick:qt,loading:Ze.value},{default:x(()=>[...s[46]||=[a(`发送测试消息`,-1)]]),_:1},8,[`loading`]),v(l,{size:`small`,variant:`tonal`,color:`primary`,"prepend-icon":`mdi-content-save`,onClick:It,loading:et.value},{default:x(()=>[...s[47]||=[a(`保存 Telegram 配置`,-1)]]),_:1},8,[`loading`])]),v(D,{class:`my-3`}),s[57]||=d(`div`,{class:`text-subtitle-2 mb-1`},`告警通知项目`,-1),s[58]||=d(`p`,{class:`text-caption text-medium-emphasis mb-3`},` 关闭后该类告警仍记录日志,但不发送 Telegram 消息。Bot Token 未配置时全部静默。 `,-1),(b(!0),u(E,null,m(at.value,(e,t)=>(b(),u(E,{key:t},[d(`div`,xe,T(t),1),(b(!0),u(E,null,m(e,e=>(b(),c(pe,{key:e.key,"model-value":tt.value[e.key]??!0,label:e.label,hint:e.desc,"persistent-hint":``,color:`primary`,density:`compact`,"hide-details":`auto`,class:`mb-1`,disabled:nt.value===e.key,"onUpdate:modelValue":t=>Kt(e.key,!!t)},null,8,[`model-value`,`label`,`hint`,`disabled`,`onUpdate:modelValue`]))),128))],64))),128)),v(D,{class:`my-3`}),s[59]||=d(`div`,{class:`text-subtitle-2 mb-1`},`子机离线告警专用 Bot(可选)`,-1),s[60]||=d(`p`,{class:`text-caption text-medium-emphasis mb-3`},` 与上方默认 Bot 分离:仅「子机离线告警」走此通道。Bot Token 与 Chat ID 均填写后生效;留空则离线告警仍走默认 Bot。 `,-1),v(N,{modelValue:G.value,"onUpdate:modelValue":s[12]||=e=>G.value=e,label:`离线告警 Bot Token`,variant:`outlined`,density:`compact`,class:`mb-3`,placeholder:K.value?`已配置(留空保持不变)`:`输入专用 Bot Token`,type:q.value?`text`:`password`,"append-inner-icon":q.value?`mdi-eye-off`:`mdi-eye`,"onClick:appendInner":Vt},null,8,[`modelValue`,`placeholder`,`type`,`append-inner-icon`]),K.value&&!G.value?(b(),c(g,{key:1,size:`small`,color:`success`,variant:`tonal`,class:`mb-3`},{default:x(()=>[...s[48]||=[a(` 离线 Token 已配置 `,-1)]]),_:1})):o(``,!0),v(N,{modelValue:H.value.telegram_offline_chat_id,"onUpdate:modelValue":s[13]||=e=>H.value.telegram_offline_chat_id=e,label:`离线告警 Chat ID`,variant:`outlined`,density:`compact`,class:`mb-3`},null,8,[`modelValue`]),s[61]||=d(`p`,{class:`text-caption text-medium-emphasis mb-3`},[a(` 检测规则与默认 Bot 相同:群聊需拉入专用 Bot 后在群内发送 `),d(`code`,null,`/start@Bot用户名`),a(`。 `)],-1),d(`div`,Se,[v(l,{size:`small`,variant:`tonal`,"prepend-icon":`mdi-radar`,loading:qe.value,onClick:Bt},{default:x(()=>[...s[49]||=[a(` 检测离线 Chat ID `,-1)]]),_:1},8,[`loading`]),v(l,{size:`small`,variant:`tonal`,"prepend-icon":`mdi-message-text`,loading:Ke.value,onClick:zt},{default:x(()=>[...s[50]||=[a(` 测试离线通道 `,-1)]]),_:1},8,[`loading`]),v(l,{size:`small`,variant:`tonal`,color:`primary`,"prepend-icon":`mdi-content-save`,loading:Ge.value,onClick:Rt},{default:x(()=>[...s[51]||=[a(` 保存离线 Bot `,-1)]]),_:1},8,[`loading`])]),v(D,{class:`my-4`}),s[62]||=d(`div`,{class:`text-subtitle-2 mb-1`},`Layer 3 宿主机巡检`,-1),s[63]||=d(`p`,{class:`text-caption text-medium-emphasis mb-3`},[a(` 每分钟由宿主机 cron 执行 `),d(`code`,null,`health_monitor.sh`),a(`:连续 3 次 /health 失败则自动重启并推送 Telegram。 配置保存后会自动同步至 .env;亦可手动同步。未同步时脚本会从数据库读取 Telegram 配置。 `)],-1),d(`div`,Ce,[v(g,{size:`small`,color:X.value?.telegram_layer3_ready?`success`:`warning`,variant:`tonal`},{default:x(()=>[a(T(X.value?.telegram_layer3_ready?`巡检 Telegram 就绪`:`请先配置 Telegram`),1)]),_:1},8,[`color`]),X.value?(b(),c(g,{key:0,size:`small`,color:X.value.telegram_env_synced?`success`:`grey`,variant:`tonal`},{default:x(()=>[a(T(X.value.telegram_env_synced?`.env 已同步`:`.env 未同步(可用 DB 回退)`),1)]),_:1},8,[`color`])):o(``,!0)]),d(`div`,we,[v(l,{size:`small`,variant:`tonal`,"prepend-icon":`mdi-sync`,onClick:Ft,loading:it.value,disabled:!X.value?.telegram_app_configured},{default:x(()=>[...s[52]||=[a(` 同步巡检 Telegram `,-1)]]),_:1},8,[`loading`,`disabled`]),v(l,{size:`small`,variant:`text`,"prepend-icon":`mdi-refresh`,onClick:Pt,loading:rt.value},{default:x(()=>[...s[53]||=[a(` 刷新状态 `,-1)]]),_:1},8,[`loading`])]),X.value?(b(),u(`p`,Te,[s[54]||=a(` 宿主机安装 cron`,-1),d(`code`,null,T(X.value.cron_install_command),1),s[55]||=a(` · 日志:`,-1),d(`code`,null,T(X.value.health_log_path),1)])):o(``,!0)]),_:1})]),_:1})]),_:1}),v(n,{cols:`12`,lg:`6`},{default:x(()=>[v(M,{elevation:`0`,border:``,rounded:`lg`,class:`mb-4`},{default:x(()=>[v(k,{class:`d-flex align-center`},{default:x(()=>[v(i,{class:`mr-2`},{default:x(()=>[...s[64]||=[a(`mdi-lock`,-1)]]),_:1}),s[65]||=a(` 修改密码 `,-1)]),_:1}),v(D),v(A,null,{default:x(()=>[v(N,{modelValue:Z.value.current,"onUpdate:modelValue":s[14]||=e=>Z.value.current=e,label:`当前密码`,variant:`outlined`,density:`compact`,type:`password`,class:`mb-3`,rules:[h(F)(`密码`)]},null,8,[`modelValue`,`rules`]),v(N,{modelValue:Z.value.new_pw,"onUpdate:modelValue":s[15]||=e=>Z.value.new_pw=e,label:`新密码`,variant:`outlined`,density:`compact`,type:`password`,class:`mb-3`,rules:[h(F)(`密码`)]},null,8,[`modelValue`,`rules`]),v(N,{modelValue:Z.value.confirm,"onUpdate:modelValue":s[16]||=e=>Z.value.confirm=e,label:`确认新密码`,variant:`outlined`,density:`compact`,type:`password`,class:`mb-3`,rules:[h(F)(`确认密码`),h(fe)(()=>Z.value.new_pw)]},null,8,[`modelValue`,`rules`]),h(L).admin?.totp_enabled?(b(),c(N,{key:0,modelValue:Z.value.totp_code,"onUpdate:modelValue":s[17]||=e=>Z.value.totp_code=e,label:`TOTP 验证码`,variant:`outlined`,density:`compact`,type:`text`,inputmode:`numeric`,maxlength:`6`,class:`mb-3`,rules:h(L).admin?.totp_enabled?[h(F)(`验证码`)]:[]},null,8,[`modelValue`,`rules`])):o(``,!0)]),_:1}),v(j,{class:`px-4 pb-4`},{default:x(()=>[v(C),v(l,{color:`primary`,variant:`flat`,onClick:Xt,loading:ct.value},{default:x(()=>[...s[66]||=[a(`修改密码`,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1}),v(M,{elevation:`0`,border:``,rounded:`lg`,class:`mb-4`},{default:x(()=>[v(k,{class:`d-flex align-center`},{default:x(()=>[v(i,{class:`mr-2`},{default:x(()=>[...s[67]||=[a(`mdi-shield-key`,-1)]]),_:1}),s[68]||=a(` 双因素认证 (TOTP) `,-1)]),_:1}),v(D),v(A,null,{default:x(()=>[d(`div`,Ee,[s[69]||=d(`span`,{class:`text-body-2`},`状态:`,-1),v(g,{color:h(L).admin?.totp_enabled?`success`:`grey`,size:`small`,variant:`tonal`,label:``,class:`ml-2`},{default:x(()=>[a(T(h(L).admin?.totp_enabled?`已启用`:`未启用`),1)]),_:1},8,[`color`])]),lt.value?(b(),u(`div`,De,[d(`img`,{src:lt.value,alt:`TOTP QR`,style:{"max-width":`200px`}},null,8,Oe),ut.value?(b(),u(`div`,ke,[d(`code`,Ae,T(ut.value),1),v(l,{size:`x-small`,variant:`text`,icon:`mdi-content-copy`,onClick:tn})])):o(``,!0),s[70]||=d(`div`,{class:`text-caption text-medium-emphasis mt-1`},`用认证器 App 扫描二维码或手动输入密钥`,-1)])):o(``,!0),h(L).admin?.totp_enabled?(b(),c(l,{key:2,size:`small`,variant:`tonal`,color:`error`,"prepend-icon":`mdi-shield-off`,onClick:$t},{default:x(()=>[...s[73]||=[a(`禁用 TOTP`,-1)]]),_:1})):(b(),u(`div`,je,[lt.value?(b(),u(`div`,Me,[v(N,{modelValue:dt.value,"onUpdate:modelValue":s[18]||=e=>dt.value=e,label:`验证码`,variant:`outlined`,density:`compact`,style:{"max-width":`160px`}},null,8,[`modelValue`]),v(l,{color:`primary`,variant:`flat`,size:`small`,onClick:Qt,loading:ft.value},{default:x(()=>[...s[72]||=[a(`启用`,-1)]]),_:1},8,[`loading`])])):(b(),c(l,{key:0,size:`small`,variant:`tonal`,"prepend-icon":`mdi-qrcode`,onClick:Zt},{default:x(()=>[...s[71]||=[a(`生成二维码`,-1)]]),_:1}))]))]),_:1})]),_:1}),v(M,{elevation:`0`,border:``,rounded:`lg`,class:`mb-4`},{default:x(()=>[v(k,{class:`d-flex align-center`},{default:x(()=>[v(i,{class:`mr-2`},{default:x(()=>[...s[74]||=[a(`mdi-key`,-1)]]),_:1}),s[75]||=a(` API Key `,-1)]),_:1}),v(D),v(A,null,{default:x(()=>[d(`div`,Ne,[v(N,{"model-value":Q.value?_t.value:`••••••••`,label:`API Key`,variant:`outlined`,density:`compact`,readonly:``,type:Q.value?`text`:`password`,style:{"max-width":`320px`}},null,8,[`model-value`,`type`]),v(l,{variant:`text`,size:`small`,icon:Q.value?`mdi-eye-off`:`mdi-eye`,onClick:nn,loading:vt.value},null,8,[`icon`,`loading`]),v(l,{variant:`text`,size:`small`,icon:`mdi-content-copy`,onClick:an})])]),_:1})]),_:1}),v(M,{elevation:`0`,border:``,rounded:`lg`},{default:x(()=>[v(k,{class:`d-flex align-center`},{default:x(()=>[v(i,{class:`mr-2`},{default:x(()=>[...s[76]||=[a(`mdi-ip-network`,-1)]]),_:1}),s[77]||=a(` 登录 IP 白名单 `,-1)]),_:1}),v(D),v(A,null,{default:x(()=>[v(pe,{modelValue:bt.value,"onUpdate:modelValue":[s[19]||=e=>bt.value=e,on],label:`启用 IP 白名单(仅白名单 IP 可登录)`,color:`primary`,density:`compact`,"hide-details":``,class:`mb-4`},null,8,[`modelValue`]),s[80]||=d(`div`,{class:`text-subtitle-2 mb-2`},`代理订阅`,-1),s[81]||=d(`p`,{class:`text-caption text-medium-emphasis mb-2`},` 填写 SS/VMess/VLESS 等订阅链接,保存后每 2 小时自动刷新节点 IP 并合并进白名单。 `,-1),v(N,{modelValue:xt.value,"onUpdate:modelValue":s[20]||=e=>xt.value=e,label:`订阅 URL`,variant:`outlined`,density:`compact`,class:`mb-2`,placeholder:`https://example.com/sub?token=...`},null,8,[`modelValue`]),d(`div`,Pe,[v(l,{size:`small`,variant:`tonal`,"prepend-icon":`mdi-cloud-download`,onClick:sn,loading:Et.value},{default:x(()=>[...s[78]||=[a(`解析预览`,-1)]]),_:1},8,[`loading`]),v(l,{size:`small`,variant:`tonal`,color:`primary`,"prepend-icon":`mdi-content-save`,onClick:cn,loading:Tt.value},{default:x(()=>[...s[79]||=[a(`保存白名单`,-1)]]),_:1},8,[`loading`])]),$.value.length?(b(),u(`div`,Fe,[d(`div`,Ie,[a(` 订阅节点 `+T($.value.length)+` 个 `,1),Ct.value?(b(),u(`span`,Le,` · 上次刷新 `+T(Ct.value),1)):o(``,!0)]),d(`div`,Re,[(b(!0),u(E,null,m(kt.value,e=>(b(),c(g,{key:e,size:`x-small`,variant:`tonal`,label:``},{default:x(()=>[a(T(e),1)]),_:2},1024))),128)),$.value.length>kt.value.length?(b(),c(g,{key:0,size:`x-small`,variant:`text`,label:``},{default:x(()=>[a(` +`+T($.value.length-kt.value.length)+` 更多 `,1)]),_:1})):o(``,!0)])])):xt.value?(b(),u(`div`,ze,T(Ct.value?`上次刷新 ${Ct.value},暂无节点`:`等待首次刷新…保存订阅 URL 后将自动拉取`),1)):o(``,!0),v(D,{class:`my-3`}),s[82]||=d(`div`,{class:`text-subtitle-2 mb-2`},`手动 IP`,-1),v(me,{modelValue:St.value,"onUpdate:modelValue":s[21]||=e=>St.value=e,label:`手动 IP / CIDR(每行一个)`,variant:`outlined`,density:`compact`,rows:`4`,class:`mb-2`,placeholder:`1.2.3.4
10.0.0.0/24`},null,8,[`modelValue`]),d(`div`,Be,` 手动 IP 与订阅节点合并生效;共 `+T(wt.value)+` 条(去重后)。 `,1)]),_:1})]),_:1})]),_:1})]),_:1}),v(de,{modelValue:Dt.value,"onUpdate:modelValue":s[24]||=e=>Dt.value=e,"max-width":`520`},{default:x(()=>[v(M,{border:``},{default:x(()=>[v(k,null,{default:x(()=>[...s[83]||=[a(`订阅解析预览`,-1)]]),_:1}),v(A,null,{default:x(()=>[d(`div`,Ve,[s[84]||=a(`共解析出 `,-1),d(`strong`,null,T(Ot.value.length),1),s[85]||=a(` 个节点 IP / 域名:`,-1)]),d(`div`,He,[(b(!0),u(E,null,m(Ot.value,e=>(b(),c(g,{key:e,size:`small`,variant:`tonal`,label:``},{default:x(()=>[a(T(e),1)]),_:2},1024))),128))]),s[86]||=d(`div`,{class:`text-caption text-medium-emphasis`},`点击「保存白名单」后才会写入订阅 URL 并触发后台刷新。`,-1)]),_:1}),v(j,null,{default:x(()=>[v(C),v(l,{variant:`text`,onClick:s[22]||=e=>Dt.value=!1},{default:x(()=>[...s[87]||=[a(`关闭`,-1)]]),_:1}),v(l,{color:`primary`,variant:`flat`,onClick:s[23]||=e=>{Dt.value=!1,cn()}},{default:x(()=>[...s[88]||=[a(`保存白名单`,-1)]]),_:1})]),_:1})]),_:1})]),_:1},8,[`modelValue`]),v(de,{modelValue:J.value,"onUpdate:modelValue":s[26]||=e=>J.value=e,"max-width":`480`},{default:x(()=>[v(M,{border:``},{default:x(()=>[v(k,null,{default:x(()=>[...s[89]||=[a(`选择 Chat ID`,-1)]]),_:1}),v(A,null,{default:x(()=>[$e.value.length?(b(),c(le,{key:1,density:`compact`,lines:`two`},{default:x(()=>[(b(!0),u(E,null,m($e.value,e=>(b(),c(se,{key:e.id,title:e.title||e.username||`Chat ${e.id}`,subtitle:`${ot(e.type)}${e.username?` · @`+e.username:``} · ID ${e.id}`,onClick:t=>Yt(e)},null,8,[`title`,`subtitle`,`onClick`]))),128))]),_:1})):(b(),u(`div`,Ue,[...s[90]||=[a(` 未检测到对话。私聊请向 Bot 发消息;群聊请将 Bot 拉入群后在群内发送 `,-1),d(`code`,null,`/start@Bot用户名`,-1),a(`,然后重新检测。 `,-1)]]))]),_:1}),v(j,null,{default:x(()=>[v(C),v(l,{variant:`text`,onClick:s[25]||=e=>J.value=!1},{default:x(()=>[...s[91]||=[a(`关闭`,-1)]]),_:1})]),_:1})]),_:1})]),_:1},8,[`modelValue`]),v(de,{modelValue:pt.value,"onUpdate:modelValue":s[30]||=e=>pt.value=e,"max-width":`400`},{default:x(()=>[v(M,{border:``},{default:x(()=>[v(k,null,{default:x(()=>[...s[92]||=[a(`禁用 TOTP`,-1)]]),_:1}),v(A,null,{default:x(()=>[v(N,{modelValue:mt.value,"onUpdate:modelValue":s[27]||=e=>mt.value=e,label:`当前密码`,variant:`outlined`,density:`compact`,type:`password`,class:`mb-2`,rules:[h(F)()]},null,8,[`modelValue`,`rules`]),v(N,{modelValue:ht.value,"onUpdate:modelValue":s[28]||=e=>ht.value=e,label:`验证码`,variant:`outlined`,density:`compact`,rules:[h(F)()]},null,8,[`modelValue`,`rules`])]),_:1}),v(j,null,{default:x(()=>[v(C),v(l,{variant:`text`,onClick:s[29]||=e=>pt.value=!1},{default:x(()=>[...s[93]||=[a(`取消`,-1)]]),_:1}),v(l,{color:`error`,variant:`flat`,onClick:en,loading:gt.value},{default:x(()=>[...s[94]||=[a(`禁用`,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1})]),_:1},8,[`modelValue`])]),_:1}))}});export{z as default};