UNPKG

mira-app-server

Version:

Mira Server - standalone server application using mira-app-core

2 lines (1 loc) 18 kB
import{am as Oe,bi as Ae,aT as m,aQ as Be,a9 as Y,aM as Je,ae as c,aa as r,a$ as i,b5 as e,aj as a,bB as n,u as g,i as L,aX as T,t as P,C as ee,aG as Re,b3 as f,aV as Ee,bp as qe,ai as u,s as se,_ as te,aI as F,ab as x,bE as ae,ac as k,E as H,G as le,H as ne,J as oe,a1 as ie,bC as Ze,bx as He,K as _e,a2 as Qe,M as We,N as Ge,O as ye,Q as ge,x as Ke,y as Xe,z as Ye,A as es,B as xe,a7 as ke,aO as o}from"./index-BAS7XAoe.js";import{p as C,_ as ss}from"./Switch.vue_vue_type_script_setup_true_lang-C04AH2zb.js";import{u as ts}from"./useLibrary-lubOK0Bg.js";import{u as as}from"./usePluginSources-D4fn3gye.js";import{_ as O}from"./Label.vue_vue_type_script_setup_true_lang-DJnzkt8b.js";import{_ as ls,a as ns,b as os,c as we}from"./DropdownMenuTrigger.vue_vue_type_script_setup_true_lang-lUdqzzfB.js";import{u as is,_ as rs}from"./useConfirmDialog-D9KV7rp5.js";import{J as he,L as be,M as re,Z as Q,v as us,s as cs,z as ds,c as ms,F as fs}from"./index-CsJj9qiO.js";const vs={class:"space-y-6"},ps={class:"flex items-center justify-between"},_s={class:"text-2xl font-bold"},ys={class:"flex gap-2"},gs={key:0,class:"grid gap-4 md:grid-cols-2 lg:grid-cols-3"},xs={class:"flex items-center gap-3"},ks={class:"relative max-w-sm flex-1"},ws={key:0,class:"grid gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5"},hs={class:"flex items-start gap-3"},bs=["src"],Cs={key:1,class:"material-icons text-xl"},$s={key:2},zs={class:"min-w-0 flex-1"},Vs={class:"truncate text-sm font-semibold"},Ss={class:"truncate text-xs text-muted-foreground"},Us={class:"line-clamp-2 min-h-[2.5rem] text-xs text-muted-foreground"},Ls={key:0,class:"flex flex-wrap gap-1"},Ps={class:"flex items-center justify-between border-t pt-3"},js={key:0,class:"flex flex-wrap justify-end gap-1"},Is={key:1,class:"py-12 text-center text-muted-foreground"},Ns={key:2,class:"py-12 text-center text-muted-foreground"},Ms={class:"min-w-0"},Ds={key:0,class:"font-medium text-foreground"},Ts={key:1,class:"text-yellow-600 dark:text-yellow-400"},Fs={key:2,class:"ml-1 text-xs"},Os={class:"px-6 pb-3 shrink-0"},As={key:0,class:"rounded-md border border-yellow-500/40 bg-yellow-500/5 p-3 text-sm text-muted-foreground"},Bs={key:1,class:"relative"},Js={class:"grid grid-cols-1 gap-3 px-6 pb-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"},Rs={class:"flex items-start gap-3"},Es={class:"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-muted text-xl"},qs=["src"],Zs={key:1,class:"material-icons text-xl"},Hs={key:2},Qs={class:"min-w-0 flex-1"},Ws=["href"],Gs={class:"truncate text-xs text-muted-foreground"},Ks={key:0},Xs={class:"line-clamp-3 min-h-[3.75rem] text-sm text-muted-foreground"},Ys={class:"mt-auto flex items-center justify-between gap-2"},et={class:"flex min-w-0 items-center gap-1"},st={key:0,class:"py-12 text-center text-sm text-muted-foreground"},tt={key:1,class:"py-12 text-center text-sm text-muted-foreground"},at={key:2,class:"py-12 text-center text-sm text-muted-foreground"},lt={class:"space-y-2"},nt={class:"space-y-2"},ot={class:"space-y-2"},it={class:"space-y-2"},rt={class:"space-y-2"},ut={key:0,class:"text-sm text-muted-foreground"},xt=Oe({__name:"index",setup(ct){const{t:d}=Ae(),{confirmDialog:A,requireConfirm:Ce}=is(),{selectedId:p}=ts(),$=m([]),W=m(!1),B=m(""),G=Be({}),j=m(!1),I=m(null),J=m(""),K=m(!1),R=m(""),E=m(!1),z=m("repository"),v=m({name:"",version:"latest",npmSource:"npmmirror",proxy:""}),h=m(null),V=m(!1),{activeSource:w}=as(),b=m([]),N=m(!1);async function ue(){var t;const l=(t=w.value)==null?void 0:t.url;if(!l){b.value=[];return}N.value=!0;try{const s=await fetch(l);if(!s.ok)throw new Error(`HTTP ${s.status}`);const y=await s.json(),_=Array.isArray(y)?y:(y==null?void 0:y.plugins)??[];b.value=_.filter(U=>U&&U.name)}catch{f.error("推荐列表加载失败,请检查插件源 URL"),b.value=[]}finally{N.value=!1}}function $e(){K.value=!0,b.value=[],ue()}const M=m(!1);async function ze(){if(p.value){M.value=!0;try{await C.syncMeta(p.value),f.success(d("common.success")),await D()}catch{f.error(d("common.failed"))}finally{M.value=!1}}}const q=Y(()=>$.value.flatMap(l=>l.plugins.map(t=>t.name))),ce=Y(()=>{if(!R.value)return b.value;const l=R.value.toLowerCase();return b.value.filter(t=>t.name.toLowerCase().includes(l)||(t.title||"").toLowerCase().includes(l)||(t.description||"").toLowerCase().includes(l))}),de=Y(()=>{const l=$.value.find(s=>s.id===p.value);if(!l)return[];if(!B.value)return l.plugins;const t=B.value.toLowerCase();return l.plugins.filter(s=>s.name.toLowerCase().includes(t)||s.author.toLowerCase().includes(t)||s.description&&s.description.toLowerCase().includes(t))});function me(l,t){return(G[l]||[]).filter(s=>s.pluginName===t)}const Ve={general:"通用",security:"安全",storage:"存储",ui:"界面",utility:"工具",integration:"集成",development:"开发"};function fe(l){return Ve[l||"general"]||l||"通用"}function X(l){return!!l&&(l.startsWith("http")||l.startsWith("/api/")||l.startsWith("/"))}function ve(l){return!!l&&!X(l)&&/^[a-z0-9_]+$/i.test(l)}async function D(){W.value=!0;try{const l=await C.listByLibrary();$.value=Array.isArray(l.data)?l.data:[];for(const t of $.value)Se(t.id)}catch{f.error(d("common.failed"))}finally{W.value=!1}}async function Se(l){try{G[l]=await Ee(pe,l)}catch{G[l]=[]}}async function Ue(l,t){const s=t?"active":"inactive";try{await C.updateStatus(l.libraryId,l.name,s),l.status=s,f.success(d("common.success"))}catch{f.error(d("common.failed"))}}async function Le(l){try{const t=await ke.get(`/plugins/${l.name}/config`,{params:{libraryId:l.libraryId}});J.value=JSON.stringify(t.data,null,2),I.value=l,j.value=!0}catch{f.error(d("common.failed"))}}async function Pe(){if(I.value)try{const l=JSON.parse(J.value);await C.configure(I.value.name,l,I.value.libraryId),f.success(d("common.success")),j.value=!1}catch(l){f.error(l instanceof SyntaxError?"JSON 格式错误":d("common.failed"))}}async function je(l){if(await Ce())try{await C.uninstall(l.name,l.libraryId),f.success(d("common.success")),await D()}catch{f.error(d("common.failed"))}}const S=m(null);async function Ie(l,t){if(!(!p.value||S.value)){S.value=l;try{await C.install({name:l,libraryId:p.value,registry:t}),f.success(d("common.success")),setTimeout(D,2e3)}catch{f.error(d("common.failed"))}finally{S.value=null}}}function Ne(){v.value={name:"",version:"latest",npmSource:"npmmirror",proxy:""},h.value=null,z.value="repository",E.value=!0}function Me(l){var s;const t=l.target;h.value=((s=t.files)==null?void 0:s[0])??null}const Z=m(null);async function De(){if(!p.value)return;if(z.value==="repository"){if(!v.value.name){f.error("请输入插件名称");return}}else if(!h.value){f.error("请选择插件包文件");return}V.value=!0;const l=new AbortController;Z.value=l;try{if(z.value==="repository")await C.install({name:v.value.name,version:v.value.version||void 0,libraryId:p.value,npmSource:v.value.npmSource,proxy:v.value.proxy||void 0},l.signal);else{const t=new FormData;t.append("file",h.value),t.append("libraryId",p.value),await ke.post("/plugins/upload",t,{headers:{"Content-Type":"multipart/form-data"},signal:l.signal})}f.success(d("common.success")),z.value==="repository"?(v.value.name="",v.value.version="latest"):h.value=null,setTimeout(D,2e3)}catch{l.signal.aborted?f.info("已取消安装"):f.error(d("common.failed"))}finally{V.value=!1,Z.value=null}}function Te(){Z.value?Z.value.abort():E.value=!1}const pe=qe();function Fe(l){pe.push(l.path)}return Je(D),(l,t)=>(o(),c("div",vs,[r("div",ps,[r("h1",_s,i(e(d)("plugin.title")),1),r("div",ys,[a(e(g),{variant:"outline",onClick:Ne},{default:n(()=>[a(e(be),{class:"mr-2 size-4"}),t[17]||(t[17]=u(" 安装插件 "))]),_:1}),a(e(g),{onClick:$e},{default:n(()=>[a(e(re),{class:"mr-2 size-4"}),u(" "+i(e(d)("plugin.pluginStore")),1)]),_:1})])]),W.value?(o(),c("div",gs,[(o(),c(L,null,T(6,s=>a(e(te),{key:s},{default:n(()=>[a(e(se),{class:"h-48 animate-pulse"})]),_:2},1024)),64))])):$.value.length?(o(),c(L,{key:1},[r("div",xs,[r("div",ks,[a(e(he),{class:"absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground"}),a(e(P),{modelValue:B.value,"onUpdate:modelValue":t[0]||(t[0]=s=>B.value=s),placeholder:e(d)("common.search"),class:"pl-9"},null,8,["modelValue","placeholder"])]),a(e(g),{variant:"outline",size:"sm",disabled:M.value||!e(p),onClick:ze},{default:n(()=>[a(e(Q),{class:F(["mr-1 size-4",{"animate-spin":M.value}])},null,8,["class"]),u(" "+i(M.value?"同步中...":"检查更新"),1)]),_:1},8,["disabled"])]),de.value.length?(o(),c("div",ws,[(o(!0),c(L,null,T(de.value,s=>(o(),x(e(te),{key:s.name,class:F(["group relative overflow-hidden",s.status==="active"?"ring-1 ring-green-500/40":""])},{default:n(()=>[r("div",{class:F(["absolute inset-x-0 top-0 h-1 transition-colors",s.status==="active"?"bg-green-500":"bg-transparent"])},null,2),a(e(se),{class:"space-y-3 pt-5 pb-0"},{default:n(()=>{var y;return[r("div",hs,[r("div",{class:F(["flex size-10 shrink-0 items-center justify-center rounded-lg bg-muted text-xl",s.status==="active"?"bg-green-500/10":""])},[s.icon&&X(s.icon)?(o(),c("img",{key:0,src:s.icon,class:"size-6 object-contain"},null,8,bs)):ve(s.icon)?(o(),c("span",Cs,i(s.icon),1)):s.icon?(o(),c("span",$s,i(s.icon),1)):(o(),x(e(re),{key:3,class:"size-5 text-muted-foreground"}))],2),r("div",zs,[r("h3",Vs,i(s.title||s.name),1),r("p",Ss,i(s.name)+" · v"+i(s.version),1)]),r("div",{class:"flex shrink-0 items-center gap-1",onClick:t[1]||(t[1]=ae(()=>{},["stop"]))},[a(e(ss),{"model-value":s.status==="active","onUpdate:modelValue":_=>Ue(s,_)},null,8,["model-value","onUpdate:modelValue"]),a(e(ls),null,{default:n(()=>[a(e(ns),{"as-child":""},{default:n(()=>[a(e(g),{variant:"ghost",size:"icon",class:"size-7 opacity-60 transition-opacity group-hover:opacity-100"},{default:n(()=>[a(e(us),{class:"size-4"})]),_:1})]),_:1}),a(e(os),{align:"end"},{default:n(()=>[s.configurable?(o(),x(e(we),{key:0,onClick:_=>Le(s)},{default:n(()=>[a(e(cs),{class:"mr-2 size-4"}),u(" "+i(e(d)("plugin.configure")),1)]),_:2},1032,["onClick"])):k("",!0),a(e(we),{class:"text-destructive",onClick:_=>je(s)},{default:n(()=>[a(e(ds),{class:"mr-2 size-4"}),u(" "+i(e(d)("plugin.uninstall")),1)]),_:2},1032,["onClick"])]),_:2},1024)]),_:2},1024)])]),r("p",Us,i(s.description||"-"),1),(y=s.tags)!=null&&y.length?(o(),c("div",Ls,[(o(!0),c(L,null,T(s.tags,_=>(o(),x(e(H),{key:_,variant:"secondary",class:"text-[10px] font-normal"},{default:n(()=>[u(i(_),1)]),_:2},1024))),128))])):k("",!0),r("div",Ps,[a(e(H),{variant:"outline",class:"text-[10px] font-normal text-muted-foreground"},{default:n(()=>[u(i(fe(s.category)),1)]),_:2},1024),e(p)&&me(e(p),s.name).length?(o(),c("div",js,[(o(!0),c(L,null,T(me(e(p),s.name),_=>(o(),x(e(g),{key:_.path,variant:"ghost",size:"sm",class:"h-6 gap-1 px-2 text-xs",onClick:ae(U=>Fe(_),["stop"])},{default:n(()=>{var U;return[u(i(((U=_.meta)==null?void 0:U.title)||_.name)+" ",1),a(e(ms),{class:"size-3"})]}),_:2},1032,["onClick"]))),128))])):k("",!0)])]}),_:2},1024)]),_:2},1032,["class"]))),128))])):(o(),c("div",Is,i(e(d)("common.noData")),1))],64)):(o(),c("div",Ns,i(e(d)("common.noData")),1)),a(e(ee),{open:j.value,"onUpdate:open":t[4]||(t[4]=s=>j.value=s)},{default:n(()=>[a(e(le),{class:"sm:max-w-lg"},{default:n(()=>[a(e(ne),null,{default:n(()=>[a(e(oe),null,{default:n(()=>{var s;return[u(i(e(d)("plugin.configure"))+" - "+i((s=I.value)==null?void 0:s.name),1)]}),_:1}),a(e(ie),null,{default:n(()=>t[18]||(t[18]=[u("编辑 JSON 配置")])),_:1})]),_:1}),Ze(r("textarea",{"onUpdate:modelValue":t[2]||(t[2]=s=>J.value=s),class:"min-h-[200px] w-full rounded-md border bg-muted p-3 font-mono text-sm focus:outline-none focus:ring-2 focus:ring-ring",spellcheck:"false"},null,512),[[He,J.value]]),a(e(_e),null,{default:n(()=>[a(e(g),{variant:"outline",onClick:t[3]||(t[3]=s=>j.value=!1)},{default:n(()=>[u(i(e(d)("common.cancel")),1)]),_:1}),a(e(g),{onClick:Pe},{default:n(()=>[u(i(e(d)("common.save")),1)]),_:1})]),_:1})]),_:1})]),_:1},8,["open"]),a(e(ee),{open:K.value,"onUpdate:open":t[7]||(t[7]=s=>K.value=s)},{default:n(()=>[a(e(le),{class:"w-[80vw] h-[80vh] max-w-[95vw] max-h-[90vh] sm:max-w-[95vw] flex flex-col gap-0 overflow-hidden p-0"},{default:n(()=>[a(e(ne),{class:"flex flex-row items-start justify-between gap-3 px-6 pt-6 pb-2 shrink-0"},{default:n(()=>[r("div",Ms,[a(e(oe),null,{default:n(()=>[u(i(e(d)("plugin.pluginStore")),1)]),_:1}),a(e(ie),null,{default:n(()=>[t[19]||(t[19]=u(" 当前插件源: ")),e(w)?(o(),c("span",Ds,i(e(w).name),1)):(o(),c("span",Ts,"未选择")),e(w)?(o(),c("span",Fs,"("+i(e(w).url)+")",1)):k("",!0)]),_:1})]),a(e(g),{variant:"outline",size:"icon",class:"shrink-0",disabled:N.value||!e(w),title:"刷新插件列表",onClick:ue},{default:n(()=>[a(e(Q),{class:F(["size-4",{"animate-spin":N.value}])},null,8,["class"])]),_:1},8,["disabled"])]),_:1}),r("div",Os,[e(w)?b.value.length?(o(),c("div",Bs,[a(e(he),{class:"absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground"}),a(e(P),{modelValue:R.value,"onUpdate:modelValue":t[5]||(t[5]=s=>R.value=s),placeholder:"搜索插件...",class:"pl-9"},null,8,["modelValue"])])):k("",!0):(o(),c("div",As," 请先在「设置 → 插件」中添加并选中一个插件源。 "))]),a(e(Qe),{class:"flex-1 min-h-0"},{default:n(()=>[r("div",Js,[(o(!0),c(L,null,T(ce.value,s=>(o(),x(e(te),{key:s.name,class:"overflow-hidden"},{default:n(()=>[a(e(se),{class:"flex h-full flex-col gap-3 p-4"},{default:n(()=>[r("div",Rs,[r("div",Es,[s.icon&&X(s.icon)?(o(),c("img",{key:0,src:s.icon,class:"size-6 object-contain"},null,8,qs)):ve(s.icon)?(o(),c("span",Zs,i(s.icon),1)):s.icon?(o(),c("span",Hs,i(s.icon),1)):(o(),x(e(re),{key:3,class:"size-5 text-muted-foreground"}))]),r("div",Qs,[r("a",{href:`https://www.npmjs.com/package/${s.name}`,target:"_blank",rel:"noopener noreferrer",class:"block truncate text-sm font-medium text-primary hover:underline",onClick:t[6]||(t[6]=ae(()=>{},["stop"]))},i(s.title||s.name),9,Ws),r("p",Gs,[u(i(s.name),1),s.version?(o(),c("span",Ks," · v"+i(s.version),1)):k("",!0)])])]),r("p",Xs,i(s.description),1),r("div",Ys,[r("div",et,[a(e(H),{variant:"outline",class:"text-[10px]"},{default:n(()=>[u(i(fe(s.category)),1)]),_:2},1024),q.value.includes(s.name)?(o(),x(e(H),{key:0,variant:"secondary",class:"text-[10px]"},{default:n(()=>t[20]||(t[20]=[u("已安装")])),_:1})):k("",!0)]),a(e(g),{disabled:q.value.includes(s.name)||S.value===s.name,variant:q.value.includes(s.name)?"secondary":"default",size:"sm",class:"shrink-0",onClick:y=>Ie(s.name,s.registry)},{default:n(()=>[S.value===s.name?(o(),x(e(Q),{key:0,class:"mr-1 size-3.5 animate-spin"})):k("",!0),u(" "+i(S.value===s.name?"安装中":q.value.includes(s.name)?"已安装":"安装"),1)]),_:2},1032,["disabled","variant","onClick"])])]),_:2},1024)]),_:2},1024))),128))]),N.value?(o(),c("div",st,"加载中...")):e(w)?ce.value.length?k("",!0):(o(),c("div",at,"没有找到匹配的插件")):(o(),c("div",tt,"请先在「设置 → 插件」中选择一个插件源"))]),_:1})]),_:1})]),_:1},8,["open"]),a(e(ee),{open:E.value,"onUpdate:open":t[13]||(t[13]=s=>E.value=s)},{default:n(()=>[a(e(le),{class:"sm:max-w-lg"},{default:n(()=>[a(e(ne),null,{default:n(()=>[a(e(oe),null,{default:n(()=>t[21]||(t[21]=[u("安装插件")])),_:1}),a(e(ie),null,{default:n(()=>{var s;return[u("为当前素材库「"+i(((s=$.value.find(y=>y.id===e(p)))==null?void 0:s.name)||e(p))+"」安装插件",1)]}),_:1})]),_:1}),a(e(We),{modelValue:z.value,"onUpdate:modelValue":t[12]||(t[12]=s=>z.value=s)},{default:n(()=>[a(e(Ge),{class:"w-full"},{default:n(()=>[a(e(ye),{value:"repository",class:"flex-1"},{default:n(()=>t[22]||(t[22]=[u("从仓库安装")])),_:1}),a(e(ye),{value:"local",class:"flex-1"},{default:n(()=>[a(e(fs),{class:"mr-1 size-3.5"}),t[23]||(t[23]=u(" 从本地上传 "))]),_:1})]),_:1}),a(e(ge),{value:"repository",class:"mt-4 space-y-4"},{default:n(()=>[r("div",lt,[a(e(O),null,{default:n(()=>t[24]||(t[24]=[u("插件名称")])),_:1}),a(e(P),{modelValue:v.value.name,"onUpdate:modelValue":t[8]||(t[8]=s=>v.value.name=s),placeholder:"npm 包名,如:mira-plugin-example"},null,8,["modelValue"])]),r("div",nt,[a(e(O),null,{default:n(()=>t[25]||(t[25]=[u("版本")])),_:1}),a(e(P),{modelValue:v.value.version,"onUpdate:modelValue":t[9]||(t[9]=s=>v.value.version=s),placeholder:"latest"},null,8,["modelValue"])]),r("div",ot,[a(e(O),null,{default:n(()=>t[26]||(t[26]=[u("NPM 源")])),_:1}),a(e(Ke),{modelValue:v.value.npmSource,"onUpdate:modelValue":t[10]||(t[10]=s=>v.value.npmSource=s)},{default:n(()=>[a(e(Xe),null,{default:n(()=>[a(e(Ye))]),_:1}),a(e(es),null,{default:n(()=>[a(e(xe),{value:"npmmirror"},{default:n(()=>t[27]||(t[27]=[u("npmmirror(默认)")])),_:1}),a(e(xe),{value:"npm"},{default:n(()=>t[28]||(t[28]=[u("npm")])),_:1})]),_:1})]),_:1},8,["modelValue"])]),r("div",it,[a(e(O),null,{default:n(()=>t[29]||(t[29]=[u("代理地址(可选)")])),_:1}),a(e(P),{modelValue:v.value.proxy,"onUpdate:modelValue":t[11]||(t[11]=s=>v.value.proxy=s),placeholder:"http://proxy.example.com:8080"},null,8,["modelValue"])])]),_:1}),a(e(ge),{value:"local",class:"mt-4 space-y-4"},{default:n(()=>[r("div",rt,[a(e(O),null,{default:n(()=>t[30]||(t[30]=[u("选择插件包")])),_:1}),a(e(P),{type:"file",accept:".zip,.tar.gz",onChange:Me}),t[31]||(t[31]=r("p",{class:"text-xs text-muted-foreground"},"支持 .zip 和 .tar.gz 格式",-1))]),h.value?(o(),c("div",ut," 已选择: "+i(h.value.name),1)):k("",!0)]),_:1})]),_:1},8,["modelValue"]),a(e(_e),null,{default:n(()=>[a(e(g),{variant:"outline",onClick:Te},{default:n(()=>[u(i(V.value?"取消安装":e(d)("common.cancel")),1)]),_:1}),a(e(g),{disabled:V.value,onClick:De},{default:n(()=>[V.value?(o(),x(e(Q),{key:0,class:"mr-2 size-4 animate-spin"})):(o(),x(e(be),{key:1,class:"mr-2 size-4"})),u(" "+i(V.value?"安装中...":"安装"),1)]),_:1},8,["disabled"])]),_:1})]),_:1})]),_:1},8,["open"]),a(rs,Re(e(A),{"onUpdate:open":t[14]||(t[14]=s=>e(A).open=s),onConfirm:t[15]||(t[15]=s=>e(A).resolve(!0)),onCancel:t[16]||(t[16]=s=>e(A).resolve(!1))}),null,16)]))}});export{xt as default};