2 lines
14 KiB
JavaScript
2 lines
14 KiB
JavaScript
import{r as i,j as e}from"./react-vendor-jWT2yUdV.js";import{u as X,k as D,c as L,b as M,aI as Y,O as ee,Q as se,R as ae,S as te,T as re,U as ne,P as le}from"./index-DiaaLdUu.js";import{z as m}from"./react-hot-toast-cGcFZPSt.js";import{a as oe}from"./index-DvErMbt6.js";import{j as O}from"./index-BBhZPeTB.js";import{E as A}from"./empty_state-BmDJmEaB.js";import{P as ce}from"./page_header-Dr2OAQrb.js";import{a as ie}from"./chunk-SXMLSBOY-NckgDZ9w.js";import{a as de,c as ue}from"./chunk-5PILOUBS-KHYNqMZE.js";import{c as fe}from"./chunk-TE6SZS6W-DGowl7ka.js";import{c as V}from"./chunk-NAV3ZXLI-ChbUTMf0.js";import{s as Q}from"./chunk-J6JGI6RM-Djlxjgjl.js";import{t as $}from"./chunk-6LIX6LVT-B246pOuK.js";import{g as xe,t as pe}from"./index-DE7yoXMZ.js";import{P as E}from"./plugin_manager-OIjldREQ.js";import{u as he}from"./use-dialog-CRIMuzeE.js";import{i as J}from"./chunk-2QAN2V2R-B2qCPZrG.js";import{s as K,l as B}from"./chunk-KVDW62ZT-CGYYmJoP.js";import"./qface-BZLvZXJ8.js";import"./react-router-dom-C6k78GT4.js";import"./iconBase-B7bT1FlI.js";import"./index-BsnVex0g.js";import"./chunk-M3MASYO7-B4fjH-eW.js";import"./chunk-EN4B57RQ-Ief8qCCd.js";import"./chunk-UX7UMZL5-CMHjUaC_.js";import"./useToggle-B3ZYBe5S.js";import"./usePress-BrNwsdVw.js";import"./useFocusable-DA5Croun.js";import"./chunk-WQVQ7P2I-BJd1EiqP.js";import"./useHover-DC1o5-bm.js";import"./chunk-SLABUSGS-Cmz8sGrU.js";import"./Item-D8Sud-UP.js";import"./SelectionManager-Dl9uHsLK.js";import"./DOMLayoutDelegate-DOgfSALU.js";import"./chunk-AXSF7SRE-Cr4elNVq.js";function me(a){if(a)try{const o=localStorage.getItem(D.token);if(!o)return a;const c=JSON.parse(o),x=new URL(a,window.location.origin);return x.searchParams.set("webui_token",c),x.pathname+x.search}catch{return a}}const ge=({data:a,onToggleStatus:o,onUninstall:c,onConfig:x,hasConfig:p=!1})=>{const{name:h,version:u,author:f,description:y,status:v,icon:z}=a,R=v==="active",[k,w]=i.useState(!1),[C,P]=i.useState(!1),[l]=X(D.backgroundImage,""),g=!!l,_=me(z)||`https://avatar.vercel.sh/${encodeURIComponent(h)}`,N=()=>{w(!0),o().finally(()=>w(!1))},S=()=>{w(!0),c().finally(()=>w(!1))};return e.jsxs(de,{className:L("group w-full backdrop-blur-xl rounded-2xl overflow-hidden transition-all duration-300","hover:shadow-lg hover:shadow-primary-500/10 hover:-translate-y-0.5","border border-white/60 dark:border-white/10 hover:border-primary/40",g?"bg-black/25 dark:bg-black/30":"bg-white/65 dark:bg-white/[0.04]"),shadow:"none",children:[e.jsxs(ue,{className:"p-4 flex flex-col gap-3",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"flex items-center gap-3 min-w-0",children:[e.jsx(ie,{src:_,name:f||"?",className:"flex-shrink-0",size:"sm",isBordered:!0,radius:"full",color:"default"}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("h3",{className:"text-[15px] font-bold text-default-900 dark:text-white truncate leading-tight",title:h,children:h}),e.jsxs("p",{className:"text-[11px] text-default-400 mt-0.5 truncate",children:["by ",e.jsx("span",{className:"font-medium",children:f||"未知"})]})]})]}),e.jsx(V,{size:"sm",variant:"flat",color:v==="active"?"success":v==="stopped"?"warning":"default",className:"flex-shrink-0 font-medium h-6 px-1",children:v==="active"?"运行中":v==="stopped"?"已停止":"已禁用"})]}),e.jsx("div",{className:"relative min-h-[2.5rem] cursor-pointer group/desc",onClick:()=>P(!C),children:e.jsx($,{content:y,isDisabled:!y||y.length<50||C,placement:"bottom",className:"max-w-[280px]",delay:500,children:e.jsx("p",{className:L("text-sm text-default-600 dark:text-default-400 leading-relaxed transition-all duration-300",C?"line-clamp-none":"line-clamp-2"),children:y||"暂无描述"})})}),e.jsx("div",{children:e.jsxs(V,{size:"sm",variant:"flat",color:"primary",className:"h-5 text-xs font-semibold px-0.5",classNames:{content:"px-1"},children:["v",u]})})]}),e.jsxs(fe,{className:"px-4 pb-4 pt-0 gap-3",children:[e.jsx(Q,{isDisabled:k,isSelected:R,onValueChange:N,size:"sm",color:"success",classNames:{wrapper:"group-data-[selected=true]:bg-success"},children:e.jsx("span",{className:"text-xs font-medium text-default-600",children:R?"已启用":"已禁用"})}),e.jsx("div",{className:"flex-1"}),p&&e.jsx($,{content:"插件配置",children:e.jsx(M,{isIconOnly:!0,radius:"full",size:"sm",variant:"light",color:"primary",onPress:x,children:e.jsx(xe,{size:20})})}),e.jsx($,{content:"卸载插件",color:"danger",children:e.jsx(M,{isIconOnly:!0,radius:"full",size:"sm",variant:"light",color:"danger",onPress:S,isDisabled:k,children:e.jsx(pe,{size:20})})})]})]})};function H(a,o=60){if(a.length<=o)return a;const c=a.includes("\\")?"\\":"/",x=a.split(c);if(x.length<=3)return a.substring(0,o-3)+"...";const p=x[0],h=x.slice(-2).join(c),u=`${p}${c}...${c}${h}`;return u.length>o?a.substring(0,o-3)+"...":u}function be(a,o=100){if(a.length<=o)return a;const c=/[A-Za-z]:\\[^\s'"]+/g,x=/\/[^\s'"]+(?:\/[^\s'"]+)+/g;let p=a;const h=a.match(c);if(h)for(const f of h)f.length>40&&(p=p.replace(f,H(f,40)));const u=a.match(x);if(u)for(const f of u)f.length>40&&(p=p.replace(f,H(f,40)));return p.length>o?p.substring(0,o-3)+"...":p}const T={error:(a,o)=>{const c=typeof a=="string"?be(a):a;return m.error(c,o)},success:(a,o)=>m.success(a,o),loading:(a,o)=>m.loading(a,o),custom:m.custom,dismiss:m.dismiss,remove:m.remove,promise:m.promise};function je({isOpen:a,onOpenChange:o,pluginId:c}){const[x,p]=i.useState(!1),[h,u]=i.useState([]),[f,y]=i.useState({}),[v,z]=i.useState(!1),[R,k]=i.useState(!1),[w,C]=i.useState(null),[P,l]=i.useState(!1),g=i.useRef(null),_=i.useRef({});i.useEffect(()=>{_.current=f},[f]);const N=i.useCallback(s=>{switch(s.type){case"full":s.schema&&u(s.schema);break;case"updateField":s.key&&s.field&&u(n=>n.map(t=>t.key===s.key?{...t,...s.field}:t));break;case"removeField":s.key&&u(n=>n.filter(t=>t.key!==s.key));break;case"addField":s.field&&u(n=>{const t=s.field,b=n.findIndex(r=>r.key===t.key);if(b!==-1){const r=[...n];return r[b]={...r[b],...t},r}if(s.afterKey){const r=n.findIndex(d=>d.key===s.afterKey);if(r!==-1){const d=[...n];return d.splice(r+1,0,t),d}}return[...n,t]});break;case"showField":s.key&&u(n=>n.map(t=>t.key===s.key?{...t,hidden:!1}:t));break;case"hideField":s.key&&u(n=>n.map(t=>t.key===s.key?{...t,hidden:!0}:t));break}},[]),S=i.useCallback(s=>{g.current&&g.current.close();const n=localStorage.getItem(D.token);if(!n){console.warn("未登录,无法建立 SSE 连接");return}const t=JSON.parse(n),b=E.getConfigSSEUrl(c,s),r=new Y.EventSourcePolyfill(b,{headers:{Authorization:`Bearer ${t}`,Accept:"text/event-stream"},withCredentials:!0});g.current=r,r.addEventListener("connected",d=>{const j=JSON.parse(d.data);C(j.sessionId),l(!0)}),r.addEventListener("schema",d=>{const j=JSON.parse(d.data);N(j)}),r.addEventListener("error",d=>{try{const j=JSON.parse(d.data);T.error("插件错误: "+j.message)}catch{l(!1)}}),r.onerror=()=>{l(!1)}},[c,N]),I=i.useCallback(()=>{g.current&&(g.current.close(),g.current=null),C(null),l(!1)},[]);i.useEffect(()=>(a&&c&&W(),()=>{I()}),[a,c,I]);const W=async()=>{p(!0),u([]),y({}),k(!1),I();try{const s=await E.getPluginConfig(c);u(s.schema||[]),y(s.config||{}),k(!!s.supportReactive),s.supportReactive&&S(s.config||{})}catch(s){T.error("加载配置失败: "+s.message)}finally{p(!1)}},Z=async()=>{z(!0);try{await E.setPluginConfig(c,f),T.success("Configuration saved"),o()}catch(s){T.error("Save failed: "+s.message)}finally{z(!1)}},F=i.useCallback((s,n)=>{y(t=>{const b={...t,[s]:n},r=h.find(d=>d.key===s);return r!=null&&r.reactive&&w&&P&&E.notifyConfigChange(c,w,s,n,b).catch(d=>console.error("通知配置变化失败:",d)),b})},[h,w,P,c]),q=s=>{const n=f[s.key]??s.default;switch(s.type){case"string":return e.jsx(J,{label:s.label,placeholder:s.placeholder||s.description,value:n||"",onValueChange:t=>F(s.key,t),description:s.description,className:"mb-4"},s.key);case"number":return e.jsx(J,{type:"number",label:s.label,placeholder:s.placeholder||s.description,value:String(n??0),onValueChange:t=>F(s.key,Number(t)),description:s.description,className:"mb-4"},s.key);case"boolean":return e.jsxs("div",{className:"flex justify-between items-center mb-4 p-2 bg-default-100 rounded-lg",children:[e.jsxs("div",{className:"flex flex-col",children:[e.jsx("span",{className:"text-small",children:s.label}),s.description&&e.jsx("span",{className:"text-tiny text-default-500",children:s.description})]}),e.jsx(Q,{isSelected:!!n,onValueChange:t=>F(s.key,t)})]},s.key);case"select":{const t=n!==void 0?String(n):void 0,b=s.options||[];return e.jsx(K,{label:s.label,placeholder:s.placeholder||"Select an option",selectedKeys:t?[t]:[],onSelectionChange:r=>{const d=Array.from(r)[0],j=b.find(U=>String(U.value)===d);F(s.key,j?j.value:d)},description:s.description,className:"mb-4",children:b.map(r=>e.jsx(B,{textValue:r.label,children:r.label},String(r.value)))},s.key)}case"multi-select":{const t=Array.isArray(n)?n.map(String):[],b=s.options||[];return e.jsx(K,{label:s.label,placeholder:s.placeholder||"Select options",selectionMode:"multiple",selectedKeys:new Set(t),onSelectionChange:r=>{const d=Array.from(r).map(j=>{const U=b.find(G=>String(G.value)===j);return U?U.value:j});F(s.key,d)},description:s.description,className:"mb-4",children:b.map(r=>e.jsx(B,{textValue:r.label,children:r.label},String(r.value)))},s.key)}case"html":return e.jsxs("div",{className:"mb-4",children:[s.label&&e.jsx("h4",{className:"text-small font-bold mb-1",children:s.label}),e.jsx("div",{dangerouslySetInnerHTML:{__html:s.default||""},className:"prose dark:prose-invert max-w-none"}),s.description&&e.jsx("p",{className:"text-tiny text-default-500 mt-1",children:s.description})]},s.key);case"text":return e.jsxs("div",{className:"mb-4",children:[s.label&&e.jsx("h4",{className:"text-small font-bold mb-1",children:s.label}),e.jsx("div",{className:"whitespace-pre-wrap text-default-700",children:s.default||""}),s.description&&e.jsx("p",{className:"text-tiny text-default-500 mt-1",children:s.description})]},s.key);default:return null}};return e.jsx(ee,{isOpen:a,onOpenChange:o,size:"2xl",scrollBehavior:"inside",children:e.jsx(se,{className:"rounded-3xl border border-white/70 dark:border-white/10 bg-white/92 dark:bg-zinc-900/92 backdrop-blur-2xl shadow-2xl shadow-primary-900/15",children:s=>e.jsxs(e.Fragment,{children:[e.jsx(ae,{className:"flex flex-col gap-1",children:e.jsxs("div",{className:"flex items-center gap-2",children:["插件配置: ",c,R&&e.jsx("span",{className:`text-tiny px-2 py-0.5 rounded ${P?"bg-success-100 text-success-600":"bg-warning-100 text-warning-600"}`,children:P?"已连接":"未连接"})]})}),e.jsx(te,{children:x?e.jsx("div",{className:"flex justify-center p-8",children:"Loading configuration..."}):e.jsx("div",{className:"flex flex-col gap-2",children:h.length===0?e.jsx("div",{className:"text-center text-default-500",children:"No configuration schema available."}):h.filter(n=>!n.hidden).map(q)})}),e.jsxs(re,{children:[e.jsx(M,{color:"danger",variant:"light",onPress:s,children:"关闭"}),e.jsx(M,{color:"primary",onPress:Z,isLoading:v,children:"保存"})]})]})})})}function ss(){const[a,o]=i.useState([]),[c,x]=i.useState(!1),[p,h]=i.useState(!1),u=he(),{isOpen:f,onOpen:y,onOpenChange:v}=ne(),[z,R]=i.useState(""),k=async()=>{x(!0),h(!1);try{const l=await E.getPluginList();l.pluginManagerNotFound?(h(!0),o([])):o(l.plugins)}catch(l){m.error(l.message)}finally{x(!1)}};i.useEffect(()=>{k()},[]);const w=async l=>{const g=l.status!=="active",_=g?"启用":"禁用",N=m.loading(`${_}中...`);try{await E.setPluginStatus(l.id,g),m.success(`${_}成功`,{id:N}),k()}catch(S){m.error(S.message,{id:N})}},C=async l=>new Promise((g,_)=>{let N=!1;u.confirm({title:"卸载插件",content:e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("p",{className:"text-base text-default-800",children:["确定要卸载插件「",e.jsx("span",{className:"font-semibold text-danger",children:l.name}),"」吗? 此操作不可恢复。"]}),e.jsxs("div",{className:"mt-2 bg-default-100 dark:bg-default-50/10 p-3 rounded-lg flex flex-col gap-1",children:[e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer w-fit",children:[e.jsx("input",{type:"checkbox",onChange:S=>{N=S.target.checked},className:"w-4 h-4 cursor-pointer accent-danger"}),e.jsx("span",{className:"text-small font-medium text-default-700",children:"同时删除其配置文件"})]}),e.jsxs("p",{className:"text-xs text-default-500 pl-6 break-all w-full",children:["配置目录: config/plugins/",l.id]})]})]}),confirmText:"确定卸载",cancelText:"取消",onConfirm:async()=>{const S=m.loading("卸载中...");try{await E.uninstallPlugin(l.id,N),m.success("卸载成功",{id:S}),k(),g()}catch(I){m.error(I.message,{id:S}),_(I)}},onCancel:()=>{g()}})}),P=l=>{R(l.id),y()};return e.jsxs(e.Fragment,{children:[e.jsx("title",{children:"插件管理 - SnowCat WebUI"}),e.jsxs("div",{className:"sc-page",children:[e.jsx(le,{loading:c}),e.jsx(je,{isOpen:f,onOpenChange:v,pluginId:z}),e.jsx(ce,{icon:e.jsx(O,{size:20}),title:"插件管理",description:"加载、启停与配置本地插件",actions:e.jsx(M,{isIconOnly:!0,className:"bg-white/60 dark:bg-white/10 text-default-600 dark:text-default-300 backdrop-blur-md hover:bg-white/80 dark:hover:bg-white/20",radius:"full",onPress:k,children:e.jsx(oe,{size:22})})}),p?e.jsx(A,{icon:e.jsx(O,{size:22}),title:"插件管理器未加载",description:"没有找到 plugins 目录,请确认 SnowCat 的插件目录是否存在且可读。"}):a.length===0?e.jsx(A,{icon:e.jsx(O,{size:22}),title:"暂时还没有安装插件",description:"把插件放进 plugins 目录后刷新,或到「插件商店」挑一个装上。"}):e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 justify-start items-stretch gap-3 md:gap-4",children:a.map(l=>e.jsx(ge,{data:l,onToggleStatus:()=>w(l),onUninstall:()=>C(l),onConfig:()=>{l.status!=="active"?m.error("未启用插件,无法配置插件"):l.hasConfig?P(l):m.error("此插件没有配置哦")},hasConfig:!0},l.id))})]})]})}export{ss as default};
|