@kitecd/cli 1.1.0 → 1.3.0
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/dist/doctor.js +181 -0
- package/dist/export.js +144 -0
- package/dist/ignore.js +38 -0
- package/dist/import.js +333 -0
- package/dist/index.js +213 -3
- package/dist/ops.js +338 -0
- package/dist/pack.js +15 -5
- package/dist/serve.js +27 -1
- package/dist/server/index.js +17231 -5610
- package/dist/upload.js +11 -3
- package/dist/verify.js +161 -0
- package/dist/web/assets/AuditLog-BO9BJdsk.js +1 -0
- package/dist/web/assets/ConfirmDialog-CikXU818.js +1 -0
- package/dist/web/assets/ConfirmDialog-D8avT8FJ.css +1 -0
- package/dist/web/assets/Dashboard-ho157_Gr.js +1 -0
- package/dist/web/assets/DefaultLayout-Y_852d55.js +1 -0
- package/dist/web/assets/DefaultLayout-lj5NNciV.css +1 -0
- package/dist/web/assets/FileExplorer-oxT6ZdHt.js +1 -0
- package/dist/web/assets/FolderPickerDialog-CDO-yrvE.css +1 -0
- package/dist/web/assets/FolderPickerDialog-CKohwBIP.js +1 -0
- package/dist/web/assets/LogBoard-DkvHTXcb.js +6 -0
- package/dist/web/assets/LogBoard-Dx8yNofc.css +1 -0
- package/dist/web/assets/LogTail-CuaBDDKf.js +9 -0
- package/dist/web/assets/Login-kcvq2T9U.js +1 -0
- package/dist/web/assets/Migration-C_M_Exzf.js +1 -0
- package/dist/web/assets/ProjectDetail-BTOfo71A.js +1 -0
- package/dist/web/assets/ProjectDetail-ia6-z1kZ.css +1 -0
- package/dist/web/assets/ProjectList-D_PoTDT9.js +1 -0
- package/dist/web/assets/ProjectList-YJlvRRNh.css +1 -0
- package/dist/web/assets/ProjectTagsEditor-zXN_5rwP.js +1 -0
- package/dist/web/assets/Settings-BL4hNZpU.js +1 -0
- package/dist/web/assets/Storage-B-pZjj08.js +1 -0
- package/dist/web/assets/Storage-CFbfZtA5.css +1 -0
- package/dist/web/assets/Terminal-Bh7bM6Bb.css +1 -0
- package/dist/web/assets/Terminal-fTZlKf2Y.js +7 -0
- package/dist/web/assets/{activity-DItEGOtI.js → activity-DZCOq6kQ.js} +1 -1
- package/dist/web/assets/archive-MB1JcYug.js +1 -0
- package/dist/web/assets/arrow-left-CsZYc3XK.js +1 -0
- package/dist/web/assets/{circle-alert-Bfrn_ovD.js → circle-alert-kmcvMchB.js} +1 -1
- package/dist/web/assets/clock-DIBzfDoY.js +1 -0
- package/dist/web/assets/constants-m1eFfRMw.js +1 -0
- package/dist/web/assets/copy-CNXWZJbC.js +1 -0
- package/dist/web/assets/createLucideIcon-BmsTm7z-.js +1 -0
- package/dist/web/assets/database-D6rC_24l.js +1 -0
- package/dist/web/assets/eye-off-BNUfzp8P.js +1 -0
- package/dist/web/assets/eye-vRDqRzR9.js +1 -0
- package/dist/web/assets/file-text-BxWt6is5.js +1 -0
- package/dist/web/assets/folder-CYPJgLMr.js +1 -0
- package/dist/web/assets/folder-open-DQz0XviI.js +1 -0
- package/dist/web/assets/hard-drive-DBiQxkNS.js +1 -0
- package/dist/web/assets/history-dkZbN_TB.js +1 -0
- package/dist/web/assets/house-D9JIOKIs.js +1 -0
- package/dist/web/assets/index-BZU6i5nw.js +2 -0
- package/dist/web/assets/index-BrlC5Hdt.css +1 -0
- package/dist/web/assets/loader-circle-OwtRa1dp.js +1 -0
- package/dist/web/assets/pencil-BTFuj0gA.js +1 -0
- package/dist/web/assets/plus-CcefsCv_.js +1 -0
- package/dist/web/assets/refresh-cw-OqaxwQhF.js +1 -0
- package/dist/web/assets/rotate-ccw-D8C0iiAw.js +1 -0
- package/dist/web/assets/save-D0NTjP8Q.js +1 -0
- package/dist/web/assets/scroll-text-6UwJwqap.js +1 -0
- package/dist/web/assets/{server-C33taHNn.js → server-DFHpqwVn.js} +1 -1
- package/dist/web/assets/square-terminal-C1oJyHEG.js +1 -0
- package/dist/web/assets/sun-Cg6PdQms.js +1 -0
- package/dist/web/assets/terminal-CUz5b_ol.js +1 -0
- package/dist/web/assets/trash-2-20ikd6fk.js +1 -0
- package/dist/web/assets/useIntervalRaf-CXWU2lqg.js +1 -0
- package/dist/web/index.html +3 -3
- package/package.json +11 -7
- package/scripts/postinstall.js +53 -0
- package/dist/web/assets/Dashboard-7wBCpwzp.js +0 -1
- package/dist/web/assets/DefaultLayout-Bj8fPWym.css +0 -1
- package/dist/web/assets/DefaultLayout-LaPhlICp.js +0 -1
- package/dist/web/assets/FileExplorer-DvzkxXvZ.js +0 -1
- package/dist/web/assets/LogBoard-BWAPesBz.js +0 -6
- package/dist/web/assets/LogBoard-DzW-cEqH.css +0 -1
- package/dist/web/assets/Login-BhNdUJs0.js +0 -1
- package/dist/web/assets/ProjectDetail-DZwMOEto.js +0 -1
- package/dist/web/assets/ProjectList-Czr-438J.js +0 -1
- package/dist/web/assets/Settings-OmPvcQbD.js +0 -1
- package/dist/web/assets/clock-BPXGSCIV.js +0 -1
- package/dist/web/assets/constants-iI5LEC2F.js +0 -1
- package/dist/web/assets/createLucideIcon-Cgv1AIRL.js +0 -1
- package/dist/web/assets/folder-open-jX-_Q7bA.js +0 -1
- package/dist/web/assets/index-C9LiRc31.css +0 -1
- package/dist/web/assets/index-eyx6wNyQ.js +0 -2
- package/dist/web/assets/project-BFuaDcvV.js +0 -1
- package/dist/web/assets/refresh-cw-DWmqwQRn.js +0 -1
- package/dist/web/assets/save-BkiMrL9q.js +0 -1
- package/dist/web/assets/settings-CrCWmNyB.js +0 -1
- package/dist/web/assets/square-terminal-C8toRwjx.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{A as e,B as t,D as n,E as r,F as i,M as a,P as ee,U as o,V as s,_ as c,b as l,c as u,d,f,ft as p,h as m,m as h,mt as g,n as te,p as _,pt as ne,q as v,t as y,v as b,y as x,z as S}from"./createLucideIcon-BmsTm7z-.js";import{t as re}from"./activity-DZCOq6kQ.js";import{n as ie,r as ae,t as oe}from"./rotate-ccw-D8C0iiAw.js";import{t as se}from"./archive-MB1JcYug.js";import{t as ce}from"./arrow-left-CsZYc3XK.js";import{n as le,t as ue}from"./pencil-BTFuj0gA.js";import{n as de,r as fe,t as pe}from"./history-dkZbN_TB.js";import{n as C,t as me}from"./file-text-BxWt6is5.js";import{t as he}from"./copy-CNXWZJbC.js";import{n as ge,r as _e,t as ve}from"./useIntervalRaf-CXWU2lqg.js";import{t as ye}from"./eye-vRDqRzR9.js";import{t as be}from"./folder-open-DQz0XviI.js";import{t as w}from"./folder-CYPJgLMr.js";import{n as xe,t as Se}from"./save-D0NTjP8Q.js";import{n as Ce,t as we}from"./square-terminal-C1oJyHEG.js";import{t as T}from"./loader-circle-OwtRa1dp.js";import{t as Te}from"./plus-CcefsCv_.js";import{t as E}from"./refresh-cw-OqaxwQhF.js";import{t as Ee}from"./scroll-text-6UwJwqap.js";import{t as De}from"./ProjectTagsEditor-zXN_5rwP.js";import{t as Oe}from"./trash-2-20ikd6fk.js";import{_ as ke,d as D,f as Ae,g as O,h as je,i as Me,l as Ne,m as Pe,n as Fe,o as Ie,r as k,s as Le,t as A,u as Re,v as ze,y as j}from"./index-BZU6i5nw.js";import{t as Be}from"./ConfirmDialog-CikXU818.js";var Ve=y(`shield-alert`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`M12 8v4`,key:`1got3b`}],[`path`,{d:`M12 16h.01`,key:`1drbdi`}]]),M=y(`shield-check`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`m9 12 2 2 4-4`,key:`dzmm74`}]]),He=y(`shield`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}]]),Ue=y(`sliders-horizontal`,[[`path`,{d:`M10 5H3`,key:`1qgfaw`}],[`path`,{d:`M12 19H3`,key:`yhmn1j`}],[`path`,{d:`M14 3v4`,key:`1sua03`}],[`path`,{d:`M16 17v4`,key:`1q0r14`}],[`path`,{d:`M21 12h-9`,key:`1o4lsq`}],[`path`,{d:`M21 19h-5`,key:`1rlt1p`}],[`path`,{d:`M21 5h-7`,key:`1oszz2`}],[`path`,{d:`M8 10v4`,key:`tgpxqk`}],[`path`,{d:`M8 12H3`,key:`a7s4jb`}]]),N={class:`select-none`},We={key:1,class:`w-4 h-4 inline-block`},Ge={class:`text-textMuted shrink-0 font-mono`},Ke=l({__name:`DeleteTreeView`,props:{node:{},depth:{},defaultExpand:{type:Boolean}},setup(t){let n=t,r=d(()=>n.depth??0),i=o(n.defaultExpand??r.value<1),s=d(()=>!!n.node.children&&n.node.children.length>0),c=e=>e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:e<1024*1024*1024?`${(e/1024/1024).toFixed(2)} MB`:`${(e/1024/1024/1024).toFixed(2)} GB`,l=d(()=>n.node.type===`dir`?s.value?n.node.willDelete?`text-danger`:`text-textMain`:`text-textMuted`:n.node.willDelete?`text-danger`:`text-success`);return(n,o)=>{let d=ee(`DeleteTreeView`,!0);return e(),m(`div`,N,[f(`div`,{class:`flex items-center gap-1.5 py-0.5 px-1 rounded text-xs hover:bg-white/[0.03] dark:hover:bg-white/[0.04]`,style:ne({paddingLeft:`${r.value*14+4}px`})},[s.value?(e(),m(`button`,{key:0,onClick:o[0]||=e=>i.value=!i.value,class:`w-4 h-4 flex items-center justify-center text-textMuted hover:text-textMain`,type:`button`},[i.value?(e(),_(v(fe),{key:0,class:`w-3 h-3`})):(e(),_(v(C),{key:1,class:`w-3 h-3`}))])):(e(),m(`span`,We)),t.node.type===`dir`?(e(),_(v(w),{key:2,class:p([`w-3.5 h-3.5 shrink-0`,l.value])},null,8,[`class`])):(e(),_(v(me),{key:3,class:p([`w-3.5 h-3.5 shrink-0`,l.value])},null,8,[`class`])),f(`span`,{class:p([`font-mono truncate flex-1`,l.value])},g(t.node.name||`/`),3),f(`span`,Ge,g(c(t.node.size)),1),t.node.willDelete&&t.node.type===`file`?(e(),_(v(Oe),{key:4,class:`w-3 h-3 text-danger/80 shrink-0`})):!t.node.willDelete&&t.node.type===`file`?(e(),_(v(M),{key:5,class:`w-3 h-3 text-success/80 shrink-0`})):h(``,!0)],4),i.value&&s.value?(e(!0),m(u,{key:0},a(t.node.children,t=>(e(),_(d,{key:t.path,node:t,depth:r.value+1},null,8,[`node`,`depth`]))),128)):h(``,!0)])}}}),qe={class:`flex-1 min-w-0`},P={class:`text-base font-semibold text-textMain`},Je={class:`font-mono`},F={key:0,class:`mx-6 mt-4 p-3 rounded-md bg-danger/10 border border-danger/30 flex items-start gap-2`},Ye={class:`px-6 py-4 grid grid-cols-3 gap-3 border-b border-border`},I={class:`bg-base border border-border rounded-md p-3`},L={class:`text-lg font-bold text-danger font-mono`},Xe={class:`text-[10px] text-textMuted`},Ze={class:`bg-base border border-border rounded-md p-3`},Qe={class:`text-lg font-bold text-success font-mono`},$e={class:`bg-base border border-border rounded-md p-3`},et={class:`text-lg font-bold text-textMain font-mono`},R={key:0,class:`text-[10px] text-yellow-400`},z={key:1,class:`text-[10px] text-textMuted`},B={key:1,class:`px-6 py-3 border-b border-border flex items-center gap-2 flex-wrap`},tt={class:`flex-1 overflow-y-auto px-4 py-3 min-h-[200px]`},V={key:0,class:`flex items-center justify-center py-10 text-textMuted`},nt={key:1,class:`text-sm text-danger py-6 text-center`},rt={key:2,class:`text-textMuted text-sm py-6 text-center`},it={class:`px-6 py-3 border-t border-border flex items-center justify-between`},at={key:0,class:`text-[11px] text-textMuted`},ot={key:1},st=A(l({__name:`CleanPreviewDialog`,props:{open:{type:Boolean},loading:{type:Boolean},error:{},preview:{},mode:{},protectPaths:{}},emits:[`update:open`],setup(n,{emit:r}){let i=n,ee=r,s=d(()=>i.mode===`clean-all`),c=d(()=>i.preview?.summary),l=d(()=>i.preview?.tree),te=e=>e==null?`-`:e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(2)} MB`;function ne(){ee(`update:open`,!1)}let y=o([]);return S(()=>i.protectPaths,e=>{y.value=[...e||[]]},{immediate:!0}),(r,i)=>(e(),_(D,{name:`fade`},{default:t(()=>[n.open?(e(),m(`div`,{key:0,class:`fixed inset-0 z-[60] flex items-center justify-center bg-black/60 backdrop-blur-sm`,onClick:j(ne,[`self`])},[f(`div`,{class:p([`bg-panel border rounded-xl w-full max-w-2xl shadow-2xl flex flex-col max-h-[85vh]`,s.value?`border-danger/40`:`border-yellow-400/30`])},[f(`div`,{class:p([`px-6 py-4 border-b flex items-start gap-3`,s.value?`border-danger/30`:`border-border`])},[f(`div`,{class:p([`w-10 h-10 rounded-lg flex items-center justify-center shrink-0`,s.value?`bg-danger/10`:`bg-yellow-400/10`])},[s.value?(e(),_(v(Ve),{key:0,class:`w-5 h-5 text-danger`})):(e(),_(v(ye),{key:1,class:`w-5 h-5 text-yellow-400`}))],2),f(`div`,qe,[f(`h3`,P,[i[0]||=b(` 清理预览 — `,-1),f(`span`,Je,g(n.mode),1),i[1]||=f(`span`,{class:`ml-2 px-1.5 py-0.5 text-[10px] rounded bg-base border border-border text-textMuted align-middle font-mono`},`DRY-RUN`,-1)]),i[2]||=f(`p`,{class:`text-xs text-textMuted mt-1`},` 仅模拟,不会真正删除文件。下一次部署时会按"已保存"的策略自动执行清理。 `,-1)]),f(`button`,{onClick:ne,class:`text-textMuted hover:text-textMain p-1 rounded`,type:`button`},[x(v(k),{class:`w-4 h-4`})])],2),s.value?(e(),m(`div`,F,[x(v(Me),{class:`w-4 h-4 text-danger shrink-0 mt-0.5`}),i[3]||=f(`p`,{class:`text-xs text-danger leading-relaxed`},[f(`strong`,null,`clean-all`),b(` 会清空部署目录下除 `),f(`code`,{class:`font-mono bg-base px-1 rounded`},`.kite-*`),b(` 之外的`),f(`strong`,null,`全部内容`),b(`,请仔细确认 protectPaths 与预览结果。 `)],-1)])):h(``,!0),f(`div`,Ye,[f(`div`,I,[i[4]||=f(`p`,{class:`text-[10px] text-textMuted uppercase tracking-wider`},`将删除`,-1),f(`p`,L,g(c.value?.deleteFiles??`-`),1),f(`p`,Xe,g(te(c.value?.deleteBytes)),1)]),f(`div`,Ze,[i[5]||=f(`p`,{class:`text-[10px] text-textMuted uppercase tracking-wider`},`将保留`,-1),f(`p`,Qe,g(c.value?.protectFiles??`-`),1),i[6]||=f(`p`,{class:`text-[10px] text-textMuted`},`由 protectPaths 命中`,-1)]),f(`div`,$e,[i[7]||=f(`p`,{class:`text-[10px] text-textMuted uppercase tracking-wider`},`总计文件`,-1),f(`p`,et,g(c.value?.totalFiles??`-`),1),c.value?.truncated?(e(),m(`p`,R,`已截断 10000 行`)):(e(),m(`p`,z,`完整扫描`))])]),y.value.length?(e(),m(`div`,B,[i[8]||=f(`span`,{class:`text-xs text-textMuted shrink-0`},`protectPaths:`,-1),(e(!0),m(u,null,a(y.value,t=>(e(),m(`span`,{key:t,class:`text-[11px] px-2 py-0.5 rounded bg-success/10 border border-success/30 text-success font-mono`},g(t),1))),128))])):h(``,!0),f(`div`,tt,[n.loading?(e(),m(`div`,V,[x(v(T),{class:`w-4 h-4 mr-2 animate-spin`}),i[9]||=b(` 正在扫描部署目录... `,-1)])):n.error?(e(),m(`div`,nt,g(n.error),1)):!l.value||!l.value.children?.length?(e(),m(`div`,rt,` 部署目录为空,无需清理 `)):(e(),_(Ke,{key:3,node:l.value,depth:0,"default-expand":!0},null,8,[`node`]))]),f(`div`,it,[n.preview?.cached?(e(),m(`span`,at,`使用 30s 内缓存结果`)):(e(),m(`span`,ot)),f(`button`,{onClick:ne,class:`px-4 py-2 text-sm font-medium text-textMuted hover:text-textMain dark:hover:bg-white/5 hover:bg-black/5 rounded-md transition-colors`,type:`button`},`关闭`)])],2)])):h(``,!0)]),_:1}))}}),[[`__scopeId`,`data-v-e5333666`]]),ct={key:0,class:`max-w-7xl mx-auto space-y-6 pb-12`,"aria-busy":`true`},lt={key:1,class:`max-w-7xl mx-auto space-y-6 pb-12`},ut={class:`flex items-start gap-3 sm:gap-4 mb-8`},dt={class:`min-w-0 flex-1`},ft={class:`flex items-center flex-wrap gap-2 sm:gap-3`},pt={class:`text-xl sm:text-2xl font-bold text-textMain tracking-tight truncate max-w-full`},mt={class:`text-xs sm:text-sm text-textMuted mt-1 font-mono break-all`},ht={class:`flex flex-wrap items-center gap-1 border-b border-border -mt-2`},gt=[`onClick`],_t={class:`grid grid-cols-1 lg:grid-cols-12 gap-6`},vt={key:0,class:`lg:col-span-12 bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},yt={class:`px-4 py-3 border-b border-border bg-base/40 flex items-center justify-between`},bt={class:`text-sm font-semibold text-textMain flex items-center`},xt={class:`font-mono text-textMain bg-base border border-border px-1.5 py-0.5 rounded ml-2 text-[11px]`},St=[`disabled`],Ct={class:`p-4`},wt={key:0,class:`text-xs text-textMuted`},Tt={key:1,class:`text-xs text-yellow-500 flex items-start gap-1.5`},Et={key:2,class:`text-xs text-yellow-500 flex items-start gap-1.5`},Dt={class:`font-mono text-textMain mx-1`},Ot={key:3,class:`grid grid-cols-2 sm:grid-cols-3 gap-3 text-xs`},kt={class:`flex items-center gap-2`},At={class:`text-textMain font-mono`},jt={class:`flex items-center gap-2`},Mt={class:`text-textMain font-mono`},Nt={class:`flex items-center gap-2`},Pt={class:`text-textMain font-mono`},Ft={class:`flex items-center gap-2`},It={class:`text-textMain font-mono`},Lt={class:`flex items-center gap-2`},Rt={class:`text-textMain font-mono`},zt={class:`flex items-center gap-2`},Bt={class:`text-textMain font-mono`},Vt={class:`flex items-center gap-2`},Ht={class:`text-textMain font-mono`},Ut={key:0,class:`text-danger ml-1`},Wt={class:`lg:col-span-7 bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},Gt={class:`px-4 sm:px-6 py-4 sm:py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02] flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3`},Kt={class:`text-lg font-semibold text-textMain flex items-center`},qt={class:`flex items-center gap-2`},Jt=[`disabled`],Yt={class:`p-6`},Xt={key:0,class:`py-10 text-center text-sm text-textMuted`},Zt={key:1,class:`py-10 text-center text-sm text-textMuted`},Qt={key:2,class:`divide-y divide-border`},$t=[`onClick`],en={class:`flex items-center gap-2 flex-wrap`},tn={key:0,class:`inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-warning/10 border border-warning/20 text-warning`,title:`该部署是一次回滚`},nn=[`title`,`onClick`,`onKeydown`],rn={key:3,class:`inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-success/10 border border-success/30 text-success`,title:`该版本为当前线上版本`},an={class:`text-xs text-textMuted truncate`},on={key:4,class:`text-xs text-textMuted`},sn=[`onClick`],cn=[`title`],ln={class:`lg:col-span-5 bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},un={class:`px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02]`},dn={class:`text-lg font-semibold text-textMain flex items-center`},fn={class:`p-6`},pn={class:`flex flex-col sm:flex-row items-stretch sm:items-center space-y-4 sm:space-y-0 sm:space-x-4`},mn={class:`relative flex-1`},hn=[`type`,`value`],gn={class:`flex items-center space-x-2`},_n=[`disabled`],vn={class:`lg:col-span-12 bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},yn=[`aria-expanded`],bn={class:`flex items-center justify-between gap-3`},xn={class:`min-w-0`},Sn={class:`text-lg font-semibold text-textMain flex items-center`},Cn={class:`text-sm text-textMuted mt-1`},wn={class:`p-6 space-y-5`},Tn={class:`rounded-lg border border-primary/20 bg-primary/5 p-4`},En={class:`flex items-center gap-3`},Dn=[`onKeydown`],On=[`disabled`,`title`],kn={class:`text-xs text-textMuted mt-2`},An={class:`font-mono text-textMain`},jn={class:`rounded-lg border border-border bg-base p-4`},Mn={class:`flex items-center gap-2`},Nn={class:`rounded-lg border border-border bg-base p-4`},Pn={class:`flex items-center gap-2 mb-4`},Fn={class:`flex-1 text-xs text-success font-mono break-all`},In={class:`text-xs text-textMuted mb-3`},Ln={class:`font-mono text-textMain bg-panel px-1 py-0.5 rounded border border-border`},Rn={class:`text-xs text-success font-mono whitespace-pre-wrap overflow-x-auto bg-panel rounded-md p-3 border border-border mb-3`},zn={class:`space-y-2 text-xs text-textMuted`},Bn={class:`pl-3 space-y-1`},Vn={class:`text-textMuted w-24 shrink-0`},Hn={class:`text-success font-mono`},Un={class:`grid grid-cols-1 md:grid-cols-2 gap-4`},Wn={class:`rounded-lg border border-border bg-base p-4`},Gn={class:`flex items-center gap-2`},Kn={class:`flex-1 text-xs text-success font-mono break-all`},qn={class:`rounded-lg border border-border bg-base p-4 space-y-3`},Jn={class:`flex items-center gap-2`},Yn={class:`flex-1 text-xs text-success font-mono break-all`},Xn={class:`flex items-center gap-2`},Zn={class:`flex-1 text-xs text-success font-mono break-all`},Qn={class:`rounded-lg border border-primary/20 bg-primary/5 p-4 space-y-3`},$n={class:`space-y-2`},er={class:`flex items-center gap-2`},tr={class:`flex-1 text-xs text-success font-mono break-all bg-base px-2 py-1 rounded border border-border`},nr=[`disabled`,`title`],rr={class:`text-xs text-textMuted pl-[120px] -mt-1`},ir={class:`font-mono`},ar={class:`flex items-center gap-2`},or={class:`flex-1 text-xs text-success font-mono break-all bg-base px-2 py-1 rounded border border-border`},sr=[`disabled`,`title`],cr={class:`flex items-center gap-2`},lr={class:`flex-1 text-xs text-success font-mono break-all bg-base px-2 py-1 rounded border border-border`},ur=[`disabled`,`title`],dr={key:0,class:`text-xs text-yellow-500`},fr={class:`grid grid-cols-1 lg:grid-cols-12 gap-6`},pr={class:`lg:col-span-5 bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},mr={class:`px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02]`},hr={class:`text-lg font-semibold text-textMain flex items-center`},gr={class:`p-6 space-y-6`},_r=[`value`],vr={class:`pt-4 border-t border-border flex justify-end`},yr=[`disabled`],br={class:`lg:col-span-7 bg-panel border border-border rounded-xl shadow-sm overflow-visible`},xr={class:`px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02]`},Sr={class:`text-lg font-semibold text-textMain flex items-center`},Cr={class:`p-6 space-y-6`},wr={class:`block text-sm font-medium text-textMain mb-2 flex items-center`},Tr={key:0,class:`ml-2 text-[10px] text-success border border-success/40 bg-success/10 px-1.5 py-0.5 rounded`},Er={key:1,class:`ml-2 text-[10px] text-textMuted border border-border bg-base px-1.5 py-0.5 rounded`},Dr={key:0,class:`relative`,"data-pm2-picker-root":``},Or={key:0,class:`absolute z-50 mt-1 w-full max-h-72 overflow-y-auto bg-panel border border-border rounded-md shadow-lg`},kr=[`onClick`],Ar={class:`flex items-center min-w-0`},jr={key:1,class:`w-3.5 h-3.5 mr-2 shrink-0`},Mr={class:`font-mono truncate`},Nr={class:`flex items-center gap-2 shrink-0 ml-3`},Pr={class:`text-[10px] text-textMuted font-mono`},Fr={key:1},Ir={id:`pm2-apps-suggest`},Lr=[`value`],Rr={key:2,class:`mt-2 flex items-start gap-2 text-xs text-yellow-500 border border-yellow-500/30 bg-yellow-500/5 rounded-md px-3 py-2`},zr={class:`leading-relaxed`},Br={key:0},Vr={class:`pt-4 border-t border-border flex justify-end`},Hr=[`disabled`],Ur={class:`lg:col-span-7 bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},Wr={class:`px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02]`},Gr={class:`text-lg font-semibold text-textMain flex items-center`},Kr={class:`p-6 space-y-6`},qr={class:`relative`},Jr={class:`relative`},Yr={class:`mt-3 flex items-start space-x-2 cursor-pointer select-none`},Xr={class:`pt-4 border-t border-border flex justify-end`},Zr=[`disabled`],Qr={class:`lg:col-span-5 bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},$r={class:`px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02]`},ei={class:`text-lg font-semibold text-textMain flex items-center`},ti={class:`p-6 space-y-5`},ni={class:`grid grid-cols-1 md:grid-cols-3 gap-3`},ri=[`value`],ii={class:`text-xs text-textMuted mt-1 leading-relaxed`},ai={key:0},oi={class:`flex gap-2 mb-3`},si=[`onKeydown`],ci={key:0,class:`flex flex-wrap gap-2`},li=[`onClick`],ui={key:1,class:`text-xs text-textMuted italic`},di={key:1,class:`p-3 rounded-md bg-danger/10 border border-danger/30 flex items-start gap-2`},fi={class:`pt-3 border-t border-border flex items-center justify-end gap-3`},pi=[`disabled`],mi={class:`space-y-6`},hi={class:`bg-panel border border-danger/20 rounded-xl shadow-sm overflow-hidden`},gi={class:`px-6 py-4`},_i={class:`text-danger font-medium flex items-center`},vi={class:`bg-panel border border-danger/30 rounded-xl w-full max-w-lg p-6 shadow-2xl`},yi={class:`flex items-start space-x-3 mb-5`},bi={class:`p-2 rounded-lg bg-danger/10 border border-danger/20 shrink-0`},xi={class:`flex-1 min-w-0`},Si={class:`text-sm text-textMuted mt-1`},Ci={class:`font-mono text-textMain`},wi={class:`font-mono text-textMuted`},Ti={class:`space-y-3 mb-5`},Ei={class:`bg-danger/5 border border-danger/20 rounded-lg p-3`},Di={class:`text-xs font-medium text-danger mb-2 flex items-center`},Oi={class:`bg-success/5 border border-success/20 rounded-lg p-3`},ki={class:`text-xs font-medium text-success mb-2 flex items-center`},Ai={class:`text-xs text-textMain/90 space-y-1 list-disc list-inside marker:text-success/60`},ji={class:`font-mono text-textMain bg-base px-1 py-0.5 rounded text-[11px]`},Mi={class:`mb-2`},Ni={class:`block text-sm font-medium text-textMuted mb-1.5`},Pi={class:`font-mono text-textMain`},Fi=[`disabled`,`placeholder`,`onKeydown`],Ii={key:0,class:`text-xs text-danger mt-2`},Li={class:`mt-6 flex justify-end space-x-3`},Ri=[`disabled`],zi=[`disabled`],Bi=`npm install -g @kitecd/cli`,Vi=l({__name:`ProjectDetail`,setup(l){let ne=Ne(),y=Re(),S=te(),C=Fe(),w=ne.params.id,T=d(()=>S.getProjectById(w)),D=o({destPath:``,preDeploy:``,postDeploy:``,postDeployAsync:!1,categoryId:``,pm2AppName:``,tagIds:[]}),k=o({cleanMode:`merge`,protectPaths:[]}),A=o(``),M=o(!1),N=o(!1),We=o(!1),Ge=o(!1),Ke=o(``),qe=o(null),P=o(!1),Je=o(!1),F=o(``),Ye=o(`http://127.0.0.1:3000`),I=o(``),L=o(!1),Xe=o(!1),Ze=d(()=>`kite:cli-help-collapsed:${w}`);function Qe(){try{let e=localStorage.getItem(Ze.value);if(e===`1`||e===`0`){L.value=e===`1`,Xe.value=!0;return}}catch{}Xe.value=!1,L.value=R.value.length>0}function $e(){L.value=!L.value,Xe.value=!0;try{localStorage.setItem(Ze.value,L.value?`1`:`0`)}catch{}}let et=o(!0);n(async()=>{if(Ye.value=window.location.origin,await Promise.all([S.fetchProjects(),S.fetchCategories(),S.fetchTags(),ra()]),T.value){D.value.destPath=T.value.destPath||``,D.value.preDeploy=T.value.preDeploy||``,D.value.postDeploy=T.value.postDeploy||``,D.value.postDeployAsync=!!T.value.postDeployAsync,D.value.categoryId=T.value.categoryId||``,D.value.pm2AppName=T.value.pm2AppName||``,D.value.tagIds=Array.isArray(T.value.tagIds)?[...T.value.tagIds]:[],I.value=T.value.env||``;let e=T.value.cleanMode;k.value.cleanMode=e===`clean`||e===`clean-all`?e:`merge`;let t=T.value.protectPaths;if(typeof t==`string`&&t.length>0)try{let e=JSON.parse(t);k.value.protectPaths=Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}catch{k.value.protectPaths=[]}else k.value.protectPaths=[];et.value=!1,Promise.all([nt(),ia()]).catch(()=>{})}else et.value=!1,y.replace(`/projects`)});let R=o([]),z=o(!1),B=o(!1),tt=o(!1),V=o(null);async function nt(){z.value=!0;try{await S.fetchLogs(),R.value=S.logs.filter(e=>e.projectId===w).slice(0,10)}catch{R.value=[]}finally{z.value=!1,Xe.value||Qe()}}function rt(e){return e?e.slice(0,8):``}let it=o(``);async function at(e,t){if(t&&(t.stopPropagation(),t.preventDefault()),e)try{await navigator.clipboard.writeText(e),it.value=e,C.success(`已复制部署 ID`,rt(e)),setTimeout(()=>{it.value===e&&(it.value=``)},2e3)}catch(e){C.error(`复制失败`,e?.message||`请手动选择文本复制`)}}let ot=d(()=>[...R.value].sort((e,t)=>{let n=new Date(e.startTime).getTime()||0;return(new Date(t.startTime).getTime()||0)-n}).find(e=>e.status===`success`&&e.triggerSource!==`rollback`)?.id||``);function Vi(e){return!e||e.status===`running`||e.triggerSource===`rollback`?!1:!!e.artifactPath}function Hi(e){return e?e.status===`running`?`部署进行中,无法回滚`:e.triggerSource===`rollback`?`回滚记录不可再被回滚`:e.artifactPath?``:`该版本归档已被清理或过早,无法回滚`:``}function Ui(e){Vi(e)&&(V.value=e,B.value=!0)}async function Wi(){let e=V.value?.id;if(e){tt.value=!0;try{let t=await S.rollbackDeployment(e);C.success(`回滚已完成`,`新部署 ${rt(t.deployId)}`),B.value=!1,V.value=null,await nt()}catch(e){C.error(`回滚失败`,e?.message||`未知错误`)}finally{tt.value=!1}}}function Gi(e){e?y.push({path:`/logs`,query:{id:e.id,projectId:w}}):y.push({path:`/logs`,query:{projectId:w}})}function Ki(e){if(!e)return`—`;try{let t=new Date(e);return isNaN(t.getTime())?e:t.toLocaleString()}catch{return e}}async function qi(e,t=`配置已保存`){try{return Qi(e),await S.updateProject(w,e),C.success(t),!0}catch(e){let t=e?.data?.conflictProject;return e?.status===409&&t?C.error(`保存失败`,`部署目录已被项目「${t}」占用,请更换目录或修改对方项目`):C.error(`保存失败`,e?.message||`请稍后重试`),!1}}let H=o(!1);async function Ji(){if(!H.value){H.value=!0;try{await qi({categoryId:D.value.categoryId||null,tagIds:[...D.value.tagIds]},`项目基本信息已保存`)}finally{H.value=!1}}}let U=o(!1);async function Yi(){if(!U.value){U.value=!0;try{let e=D.value.pm2AppName.trim()||null,t=(T.value?.pm2AppName||``).trim()||null;await qi({pm2AppName:e},`PM2 应用绑定已保存`)&&(await ia(),e&&e!==t&&await Zi())}finally{U.value=!1}}}let W=o(!1);async function Xi(){if(!W.value){W.value=!0;try{await qi({destPath:D.value.destPath,preDeploy:D.value.preDeploy,postDeploy:D.value.postDeploy,postDeployAsync:D.value.postDeployAsync},`部署脚本已保存`)}finally{W.value=!1}}}async function Zi(){try{let e=await S.fetchProjectPm2(w);if(!e||e.found!==!0)return;let t=[];if(e.outLogPath&&t.push({path:e.outLogPath,kind:`stdout`}),e.errorLogPath&&t.push({path:e.errorLogPath,kind:`stderr`}),t.length===0)return;let n=await S.fetchLogSources(w),r=new Set((n?.items||[]).map(e=>e.filePath)),i=t.filter(e=>!r.has(e.path));if(i.length===0)return;let a=D.value.pm2AppName.trim()||`pm2`,ee=i.map(e=>({filePath:e.path,label:`${a} · ${e.kind}`,kind:`pm2`})),o=await S.createLogSources(w,ee),s=Array.isArray(o?.created)?o.created:[];s.length>0&&C.success(`已自动导入 ${s.length} 个 PM2 日志源`,`可在「运行日志」页面查看`)}catch{}}function Qi(e){let t=T.value;t&&(e.destPath!==void 0&&(t.destPath=e.destPath,t.deployPath=e.destPath),e.preDeploy!==void 0&&(t.preDeploy=e.preDeploy,t.preDeployScript=e.preDeploy),e.postDeploy!==void 0&&(t.postDeploy=e.postDeploy,t.postDeployScript=e.postDeploy),e.postDeployAsync!==void 0&&(t.postDeployAsync=!!e.postDeployAsync),e.categoryId!==void 0&&(t.categoryId=e.categoryId),e.env!==void 0&&(t.env=e.env),e.pm2AppName!==void 0&&(t.pm2AppName=e.pm2AppName),e.tagIds!==void 0&&(t.tagIds=Array.isArray(e.tagIds)?[...e.tagIds]:[]),e.cleanMode!==void 0&&(t.cleanMode=e.cleanMode),e.protectPaths!==void 0&&(t.protectPaths=Array.isArray(e.protectPaths)&&e.protectPaths.length?JSON.stringify(e.protectPaths):null),e.name!==void 0&&(t.name=e.name))}let $i=o(!1),ea=d(()=>I.value.trim()!==(T.value?.env||``));async function ta(){if(!(!ea.value||$i.value)){$i.value=!0;try{let e={env:I.value.trim()};Qi(e),await S.updateProject(w,e),C.success(`部署环境已保存`)}catch(e){C.error(`保存失败`,e?.message||`请稍后重试`)}finally{$i.value=!1}}}let G=o(!1),K=o([]),q=o(null),na=o(!1);async function ra(){try{if(G.value=await S.fetchPm2Available(),G.value)try{let e=await S.fetchPm2Apps();K.value=Array.isArray(e)?e.filter(e=>e.name):[]}catch{K.value=[]}}catch{G.value=!1}}async function ia(){if(!D.value.pm2AppName.trim()){q.value=null;return}na.value=!0;try{q.value=await S.fetchProjectPm2(w)}finally{na.value=!1}}ve(async()=>{D.value.pm2AppName.trim()&&await ia()},5e3);let J=o(!1),aa=o(!1);function oa(){J.value=!J.value}function sa(){J.value=!1}function ca(e){D.value.pm2AppName=e,aa.value=!1,sa()}function la(){aa.value=!0,sa()}let ua=d(()=>G.value&&K.value.length>0&&!aa.value),da=d(()=>{let e=D.value.pm2AppName.trim();return e?S.projects.filter(t=>t.id!==w&&(t.pm2AppName||``).trim()===e):[]});function fa(e){if(!J.value)return;let t=e.target;t&&t.closest(`[data-pm2-picker-root]`)||sa()}n(()=>{document.addEventListener(`click`,fa)}),r(()=>{document.removeEventListener(`click`,fa)});function pa(e){if(e==null||isNaN(e))return`—`;let t=1024;return e<t?`${e} B`:e<t*t?`${(e/t).toFixed(1)} KB`:e<t*t*t?`${(e/t/t).toFixed(1)} MB`:`${(e/t/t/t).toFixed(2)} GB`}function ma(e){if(e==null||e<0)return`—`;let t=Math.floor(e/1e3),n=Math.floor(t/86400),r=Math.floor(t%86400/3600),i=Math.floor(t%3600/60);return n>0?`${n}d ${r}h`:r>0?`${r}h ${i}m`:i>0?`${i}m`:`${t}s`}function ha(){let e=A.value.trim();if(e){if(k.value.protectPaths.includes(e)){A.value=``;return}k.value.protectPaths.push(e),A.value=``}}function ga(e){k.value.protectPaths=k.value.protectPaths.filter(t=>t!==e)}async function _a(){M.value=!0;try{let e={cleanMode:k.value.cleanMode,protectPaths:k.value.protectPaths.length?k.value.protectPaths:null};Qi(e),await S.updateProject(w,e),C.success(`清理策略已保存`,k.value.cleanMode===`merge`?`将沿用合并模式(零破坏)`:`下次部署会按 ${k.value.cleanMode} 执行`)}catch(e){C.error(`保存失败`,e?.message)}finally{M.value=!1,N.value=!1}}async function va(){if(k.value.cleanMode===`clean-all`){N.value=!0;return}await _a()}async function ya(){if(k.value.cleanMode===`merge`){C.info(`merge 模式不会删除任何文件,无需预览`);return}We.value=!0,Ge.value=!0,Ke.value=``,qe.value=null;try{qe.value=await S.cleanPreview(w,{cleanMode:k.value.cleanMode,protectPaths:k.value.protectPaths})}catch(e){Ke.value=e?.message||`预览失败`}finally{Ge.value=!1}}let ba=()=>{T.value?.token&&(navigator.clipboard.writeText(T.value.token),Je.value=!0,setTimeout(()=>Je.value=!1,2e3))},xa=e=>{try{let t=document.createElement(`textarea`);t.value=e,t.setAttribute(`readonly`,``),t.style.position=`fixed`,t.style.top=`0`,t.style.left=`0`,t.style.opacity=`0`,document.body.appendChild(t),t.focus(),t.select();let n=document.execCommand(`copy`);return document.body.removeChild(t),n}catch{return!1}},Y=(e,t)=>{if(!t)return;let n=()=>{F.value=e,setTimeout(()=>F.value=``,2e3)};if(xa(t)){n();return}navigator.clipboard&&window.isSecureContext?navigator.clipboard.writeText(t).then(n).catch(()=>{window.prompt(`请手动复制以下内容(Ctrl/Cmd + C):`,t)}):window.prompt(`请手动复制以下内容(Ctrl/Cmd + C):`,t)},Sa=d(()=>I.value.trim()?` --env ${I.value.trim()}`:``),Ca=d(()=>I.value.trim()?`kite.config.${I.value.trim()}.json`:`kite.config.json`),wa=d(()=>`kite init --project ${w}${Sa.value} --out ./dist --server ${Ye.value} --token ${T.value?.token||`<DEPLOY_TOKEN>`}`),Ta=d(()=>`kite push${Sa.value}`),Ea=d(()=>`kite push --server ${Ye.value} --project ${w}${Sa.value} --out ./dist`),Da=d(()=>`kite push --server ${Ye.value} --project ${w} --token ${T.value?.token||`<DEPLOY_TOKEN>`}${Sa.value} --out ./dist`),Oa=d(()=>T.value?.token||`<DEPLOY_TOKEN>`),ka=d(()=>I.value.trim()?`kite config:set token ${Oa.value} --env ${I.value.trim()}`:`kite config:set token ${Oa.value}`),Aa=d(()=>`kite config:set token ${Oa.value} --global`),ja=d(()=>`KITE_DEPLOY_TOKEN=${Oa.value}`),Ma=d(()=>JSON.stringify({projectId:w,outputDir:`./dist`,files:[`**/*`],postDeploy:T.value?.postDeploy||`pm2 restart your-service`},null,2)),Na=[{label:`打包所有文件`,files:[`**/*`]},{label:`只上传 dist 目录`,files:[`dist/**/*`]},{label:`指定多个目录`,files:[`dist/**/*`,`public/**/*`]},{label:`单个文件`,files:[`index.html`]},{label:`混合配置`,files:[`dist/**/*`,`server.js`,`config/*.json`]}],Pa=o(!1),Fa=o(!1),Ia=()=>{Pa.value=!0},La=async()=>{Fa.value=!0;try{await S.generateToken(w),P.value=!0,Pa.value=!1,C.success(`Token 已重新生成`,`旧 Token 已立即失效`)}catch(e){C.error(`Token 重置失败`,e?.message)}finally{Fa.value=!1}},Ra=o(!1),za=o(``),X=o(!1),Z=o(``),Q=d(()=>T.value?.name?.trim()||``),Ba=d(()=>!X.value&&Q.value.length>0&&za.value.trim()===Q.value);function Va(){za.value=``,Z.value=``,X.value=!1,Ra.value=!0}function Ha(){X.value||(Ra.value=!1,za.value=``,Z.value=``)}async function Ua(){if(Ba.value){X.value=!0,Z.value=``;try{await S.removeProject(w)?(Ra.value=!1,y.replace(`/projects`)):Z.value=`删除失败,请稍后重试`}catch(e){Z.value=e?.message||`删除失败,请稍后重试`}finally{X.value=!1}}}let Wa=d(()=>`kite:project-detail-tab:${w}`),$=o(`overview`),Ga=[{key:`overview`,label:`概览`,icon:Ce},{key:`config`,label:`配置`,icon:Ue},{key:`integration`,label:`危险区`,icon:Ve}];n(()=>{try{let e=localStorage.getItem(Wa.value);(e===`overview`||e===`config`||e===`integration`)&&($.value=e)}catch{}});function Ka(e){$.value=e;try{localStorage.setItem(Wa.value,e)}catch{}}return(n,r)=>{let o=ee(`router-link`);return et.value?(e(),m(`div`,ct,[...r[28]||=[c(`<div class="flex items-start gap-3 sm:gap-4 mb-8 animate-pulse"><div class="w-9 h-9 rounded-full bg-border/40 shrink-0"></div><div class="min-w-0 flex-1 space-y-3"><div class="flex items-center flex-wrap gap-2 sm:gap-3"><div class="h-7 w-48 rounded-md bg-border/40"></div><div class="h-5 w-16 rounded-md bg-border/30"></div><div class="h-7 w-24 rounded-md bg-border/30"></div><div class="h-7 w-24 rounded-md bg-border/30"></div><div class="h-7 w-24 rounded-md bg-border/30"></div></div><div class="h-3 w-72 rounded bg-border/30"></div></div></div><div class="flex flex-wrap items-center gap-1 border-b border-border -mt-2 animate-pulse"><div class="h-9 w-24 rounded-t-md bg-border/30 mr-2"></div><div class="h-9 w-24 rounded-t-md bg-border/20 mr-2"></div><div class="h-9 w-20 rounded-t-md bg-border/20"></div></div><div class="grid grid-cols-1 lg:grid-cols-12 gap-6 animate-pulse"><div class="lg:col-span-7 h-72 rounded-xl bg-panel border border-border"></div><div class="lg:col-span-5 h-72 rounded-xl bg-panel border border-border"></div><div class="lg:col-span-12 h-48 rounded-xl bg-panel border border-border"></div></div>`,3)]])):T.value?(e(),m(`div`,lt,[f(`div`,ut,[f(`button`,{onClick:r[0]||=e=>v(y).back(),class:`p-2 dark:hover:bg-white/10 hover:bg-black/10 rounded-full transition-colors text-textMuted hover:text-textMain shrink-0`},[x(v(ce),{class:`w-5 h-5`})]),f(`div`,dt,[f(`div`,ft,[f(`h1`,pt,g(T.value.name),1),f(`span`,{class:p([`px-2.5 py-0.5 text-xs rounded-md border shrink-0`,T.value.status===`success`?`bg-success/10 border-success/20 text-success`:`bg-primary/10 border-primary/20 text-primary`])},g(T.value.status),3),x(o,{to:`/projects/${v(w)}/files`,class:`inline-flex items-center px-3 py-1.5 text-xs font-medium bg-base border border-border hover:border-primary/50 hover:text-primary text-textMuted rounded-md transition-all`},{default:t(()=>[x(v(be),{class:`w-3.5 h-3.5 mr-1.5`}),r[29]||=b(` 查看文件 `,-1)]),_:1},8,[`to`]),x(o,{to:`/projects/${v(w)}/logs`,class:`inline-flex items-center px-3 py-1.5 text-xs font-medium bg-base border border-border hover:border-primary/50 hover:text-primary text-textMuted rounded-md transition-all`},{default:t(()=>[x(v(me),{class:`w-3.5 h-3.5 mr-1.5`}),r[30]||=b(` 运行日志 `,-1)]),_:1},8,[`to`]),x(o,{to:`/audit?targetId=${v(w)}`,class:`inline-flex items-center px-3 py-1.5 text-xs font-medium bg-base border border-border hover:border-primary/50 hover:text-primary text-textMuted rounded-md transition-all`},{default:t(()=>[x(v(Ee),{class:`w-3.5 h-3.5 mr-1.5`}),r[31]||=b(` 操作历史 `,-1)]),_:1},8,[`to`]),x(o,{to:`/terminal?projectId=${v(w)}`,class:`inline-flex items-center px-3 py-1.5 text-xs font-medium bg-base border border-border hover:border-primary/50 hover:text-primary text-textMuted rounded-md transition-all`},{default:t(()=>[x(v(we),{class:`w-3.5 h-3.5 mr-1.5`}),r[32]||=b(` 打开终端 `,-1)]),_:1},8,[`to`])]),f(`p`,mt,g(T.value.id),1)])]),f(`nav`,ht,[(e(),m(u,null,a(Ga,t=>f(`button`,{key:t.key,type:`button`,onClick:e=>Ka(t.key),class:p([`inline-flex items-center px-4 py-2.5 text-sm font-medium border-b-2 -mb-px transition-colors`,$.value===t.key?`border-primary text-primary`:`border-transparent text-textMuted hover:text-textMain hover:border-border`])},[(e(),_(i(t.icon),{class:`w-4 h-4 mr-1.5`})),b(` `+g(t.label),1)],10,gt)),64))]),s(f(`section`,_t,[(T.value.pm2AppName||``).trim()?(e(),m(`div`,vt,[f(`div`,yt,[f(`h3`,bt,[x(v(re),{class:`w-4 h-4 mr-2 text-primary`}),r[33]||=b(` PM2 应用状态 `,-1),f(`code`,xt,g(T.value.pm2AppName),1),r[34]||=f(`span`,{class:`ml-2 text-[10px] text-textMuted`},`每 5 秒自动刷新`,-1)]),f(`button`,{onClick:ia,disabled:na.value,class:`text-textMuted hover:text-textMain text-xs flex items-center disabled:opacity-50`},[x(v(E),{class:p([`w-3 h-3 mr-1`,na.value?`animate-spin`:``])},null,8,[`class`]),r[35]||=b(` 刷新 `,-1)],8,St)]),f(`div`,Ct,[q.value?G.value?q.value.found===!1?(e(),m(`div`,Et,[x(v(Me),{class:`w-3.5 h-3.5 mt-0.5 shrink-0`}),r[36]||=b(` 未在 PM2 中找到名为 `,-1),f(`code`,Dt,g(T.value.pm2AppName),1),r[37]||=b(` 的应用。请确认 `,-1),r[38]||=f(`code`,{class:`font-mono text-textMain mx-1`},`pm2 list`,-1),r[39]||=b(` 中存在该应用名。 `,-1)])):(e(),m(`div`,Ot,[f(`div`,kt,[f(`span`,{class:p([`w-2 h-2 rounded-full`,q.value.status===`online`?`bg-success`:`bg-danger`])},null,2),r[40]||=f(`span`,{class:`text-textMuted`},`状态`,-1),f(`span`,At,g(q.value.status||`—`),1)]),f(`div`,jt,[x(v(_e),{class:`w-3.5 h-3.5 text-textMuted`}),r[41]||=f(`span`,{class:`text-textMuted`},`CPU`,-1),f(`span`,Mt,g(q.value.cpuPercent==null?`—`:q.value.cpuPercent.toFixed(1)+`%`),1)]),f(`div`,Nt,[x(v(ge),{class:`w-3.5 h-3.5 text-textMuted`}),r[42]||=f(`span`,{class:`text-textMuted`},`内存`,-1),f(`span`,Pt,g(pa(q.value.memoryBytes)),1)]),f(`div`,Ft,[r[43]||=f(`span`,{class:`text-textMuted`},`PID`,-1),f(`span`,It,g(q.value.pid??`—`),1)]),f(`div`,Lt,[r[44]||=f(`span`,{class:`text-textMuted`},`实例`,-1),f(`span`,Rt,g(q.value.instances??1)+` (`+g(q.value.execMode||`—`)+`)`,1)]),f(`div`,zt,[r[45]||=f(`span`,{class:`text-textMuted`},`运行时长`,-1),f(`span`,Bt,g(ma(q.value.uptimeMs)),1)]),f(`div`,Vt,[r[46]||=f(`span`,{class:`text-textMuted`},`重启次数`,-1),f(`span`,Ht,[b(g(q.value.restarts??0),1),q.value.unstableRestarts?(e(),m(`span`,Ut,`(不稳定 `+g(q.value.unstableRestarts)+`)`,1)):h(``,!0)])])])):(e(),m(`div`,Tt,[x(v(Me),{class:`w-3.5 h-3.5 mt-0.5 shrink-0`}),b(` `+g(q.value.message||`服务器未检测到 PM2,无法读取应用状态。`),1)])):(e(),m(`div`,wt,g(na.value?`正在拉取…`:`尚未获取到状态`),1))])])):h(``,!0),f(`div`,Wt,[f(`div`,Gt,[f(`div`,null,[f(`h2`,Kt,[x(v(pe),{class:`w-5 h-5 mr-2 text-primary`}),r[47]||=b(` 部署历史 `,-1)]),r[48]||=f(`p`,{class:`text-sm text-textMuted mt-1`},`最近 10 次部署。点击行查看完整日志,行末可对已归档版本一键回滚。`,-1)]),f(`div`,qt,[f(`button`,{onClick:nt,disabled:z.value,class:`inline-flex items-center px-3 py-1.5 text-xs font-medium bg-base border border-border hover:border-primary/50 hover:text-primary text-textMuted rounded-md transition-all disabled:opacity-50`},[x(v(E),{class:p([`w-3.5 h-3.5 mr-1.5`,{"animate-spin":z.value}])},null,8,[`class`]),r[49]||=b(` 刷新 `,-1)],8,Jt),f(`button`,{onClick:r[1]||=e=>Gi(),class:`inline-flex items-center px-3 py-1.5 text-xs font-medium bg-base border border-border hover:border-primary/50 hover:text-primary text-textMuted rounded-md transition-all`},[x(v(Ee),{class:`w-3.5 h-3.5 mr-1.5`}),r[50]||=b(` 查看全部 `,-1)])])]),f(`div`,Yt,[z.value&&R.value.length===0?(e(),m(`div`,Xt,` 加载中… `)):R.value.length===0?(e(),m(`div`,Zt,` 该项目暂无部署记录。 `)):(e(),m(`ul`,Qt,[(e(!0),m(u,null,a(R.value,t=>(e(),m(`li`,{key:t.id,class:`flex items-center gap-3 py-3 hover:bg-black/[0.02] dark:hover:bg-white/[0.02] -mx-2 px-2 rounded-md transition-colors`},[f(`button`,{onClick:e=>Gi(t),class:`flex-1 min-w-0 text-left`},[f(`div`,en,[f(`span`,{class:p([`inline-flex items-center px-2 py-0.5 rounded text-[10px] font-medium border`,{"bg-success/10 border-success/20 text-success":t.status===`success`,"bg-danger/10 border-danger/20 text-danger":t.status===`failed`,"bg-primary/10 border-primary/20 text-primary":t.status===`running`}])},g(t.status),3),t.triggerSource===`rollback`?(e(),m(`span`,tn,` RB `)):h(``,!0),t.artifactPath?(e(),_(v(se),{key:1,class:`w-3.5 h-3.5 text-success/70`,"aria-label":`已归档`})):(e(),_(v(ae),{key:2,class:`w-3.5 h-3.5 text-textMuted/50`,"aria-label":`无归档`})),f(`span`,{role:`button`,tabindex:`0`,class:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-base border border-border font-mono text-[10px] text-textMuted hover:text-primary hover:border-primary/40 transition-colors cursor-pointer`,title:`点击复制完整 ID: ${t.id}`,onClick:j(e=>at(t.id,e),[`stop`,`prevent`]),onKeydown:ze(j(e=>at(t.id,e),[`stop`,`prevent`]),[`enter`])},[it.value===t.id?(e(),_(v(ie),{key:0,class:`w-3 h-3 text-success`})):(e(),_(v(he),{key:1,class:`w-3 h-3`})),b(` `+g(rt(t.id)),1)],40,nn),t.id===ot.value?(e(),m(`span`,rn,`当前版本`)):h(``,!0),r[51]||=f(`span`,{class:`text-xs text-textMuted`},`·`,-1),f(`span`,an,g(Ki(t.startTime)),1),t.duration?(e(),m(`span`,on,`· `+g(t.duration),1)):h(``,!0)])],8,$t),Vi(t)?(e(),m(`button`,{key:0,onClick:j(e=>Ui(t),[`stop`]),class:`inline-flex items-center px-2.5 py-1 text-xs font-medium bg-warning/10 text-warning border border-warning/20 hover:bg-warning hover:text-white rounded-md transition-all`},[x(v(oe),{class:`w-3 h-3 mr-1`}),r[52]||=b(` 回滚到此版本 `,-1)],8,sn)):(e(),m(`span`,{key:1,class:`inline-flex items-center px-2.5 py-1 text-xs font-medium bg-base text-textMuted/60 border border-border rounded-md cursor-not-allowed`,title:Hi(t)},` 不可回滚 `,8,cn))]))),128))]))])]),f(`div`,ln,[f(`div`,un,[f(`h2`,dn,[x(v(xe),{class:`w-5 h-5 mr-2 text-primary`}),r[53]||=b(` 鉴权 Token 管理 `,-1)]),r[54]||=f(`p`,{class:`text-sm text-textMuted mt-1`},`用于 CLI 或 Webhook 触发自动化部署的专属凭证。`,-1)]),f(`div`,fn,[f(`div`,pn,[f(`div`,mn,[f(`input`,{type:P.value?`text`:`password`,readonly:``,value:T.value.token||`暂无 Token,请生成`,class:p([`w-full bg-base border border-border rounded-md pl-4 pr-12 py-3 text-textMain font-mono text-sm focus:outline-none focus:border-primary/50 transition-colors`,{"opacity-50 blur-[2px] select-none":!P.value&&T.value.token}])},null,10,hn),T.value.token?(e(),m(`button`,{key:0,onClick:r[2]||=e=>P.value=!P.value,class:`absolute right-3 top-1/2 -translate-y-1/2 text-textMuted hover:text-textMain text-xs font-medium px-2 py-1 rounded transition-colors`},g(P.value?`隐藏`:`显示`),1)):h(``,!0)]),f(`div`,gn,[f(`button`,{onClick:ba,disabled:!T.value.token,class:`flex items-center justify-center px-4 py-3 bg-base border border-border hover:border-primary/50 hover:text-primary text-textMain rounded-md transition-all disabled:opacity-50 disabled:cursor-not-allowed w-full sm:w-auto`},[Je.value?(e(),_(v(Le),{key:0,class:`w-4 h-4 mr-2 text-success`})):(e(),_(v(he),{key:1,class:`w-4 h-4 mr-2`})),b(` `+g(Je.value?`已复制`:`复制`),1)],8,_n),f(`button`,{onClick:Ia,class:`flex items-center justify-center px-4 py-3 bg-primary/10 text-primary border border-primary/20 hover:bg-primary hover:text-white rounded-md transition-all w-full sm:w-auto font-medium shadow-[0_0_10px_rgba(59,130,246,0.1)] hover:shadow-[0_0_15px_rgba(59,130,246,0.4)]`},[x(v(E),{class:`w-4 h-4 mr-2`}),r[55]||=b(` 重新生成 `,-1)])])]),r[56]||=f(`div`,{class:`mt-4 p-4 rounded-md bg-primary/5 border border-primary/10 text-sm`},[f(`p`,{class:`text-textMuted leading-relaxed`},[f(`strong`,{class:`text-primary font-medium`},`CLI 用法:`),b(` 将此 Token 保存到全局配置后,`),f(`code`,{class:`bg-base px-1 py-0.5 rounded font-mono text-xs text-textMain border border-border`},`kite push`),b(` 时无需再传。 `)])],-1)])]),f(`div`,vn,[f(`div`,{class:p([`px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02] cursor-pointer select-none hover:bg-black/[0.04] dark:hover:bg-white/[0.04] transition-colors`,{"border-b-0":L.value}]),onClick:$e,role:`button`,"aria-expanded":!L.value},[f(`div`,bn,[f(`div`,xn,[f(`h2`,Sn,[x(v(we),{class:`w-5 h-5 mr-2 text-primary`}),r[57]||=b(` CLI 快速部署指引 `,-1)]),f(`p`,Cn,[L.value&&R.value.length>0?(e(),m(u,{key:0},[b(` 已有部署记录,指引已折叠 — 点击展开 `)],64)):(e(),m(u,{key:1},[b(` 三步完成部署:安装 CLI、初始化配置、推送部署。 `)],64))])]),(e(),_(i(L.value?v(fe):v(de)),{class:`w-5 h-5 text-textMuted shrink-0`}))])],10,yn),s(f(`div`,wn,[f(`div`,Tn,[r[63]||=f(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`部署环境 (可选)`,-1),f(`div`,En,[s(f(`input`,{"onUpdate:modelValue":r[3]||=e=>I.value=e,type:`text`,class:`flex-1 bg-base border border-border rounded-md px-3 py-2 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`留空为默认环境,或输入如 test、staging、prod`,onKeydown:ze(j(ta,[`prevent`]),[`enter`])},null,40,Dn),[[O,I.value]]),f(`button`,{onClick:ta,disabled:!ea.value||$i.value,class:`flex items-center px-3 py-2 bg-primary text-white rounded-md text-sm font-medium hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors`,title:ea.value?`保存当前部署环境`:`当前值未变化`},[$i.value?(e(),_(v(E),{key:0,class:`w-3.5 h-3.5 mr-1.5 animate-spin`})):(e(),_(v(Se),{key:1,class:`w-3.5 h-3.5 mr-1.5`})),r[58]||=b(` 保存 `,-1)],8,On)]),f(`p`,kn,[r[59]||=b(` 填写后下方所有指令将自动带上 `,-1),r[60]||=f(`code`,{class:`font-mono text-textMain`},`--env`,-1),r[61]||=b(` 参数,生成的配置文件为 `,-1),f(`code`,An,g(Ca.value),1),r[62]||=b(`。 适用于同一项目需要部署到不同环境(测试/预发/生产)的场景。 `,-1)])]),f(`div`,jn,[r[64]||=f(`p`,{class:`text-sm font-medium text-textMain mb-2`},`1. 安装 CLI`,-1),f(`div`,Mn,[f(`code`,{class:`flex-1 text-xs text-success font-mono break-all`},g(Bi)),f(`button`,{onClick:r[4]||=e=>Y(`install`,Bi),class:`text-xs text-primary hover:text-textMain`},g(F.value===`install`?`已复制`:`复制`),1)])]),f(`div`,Nn,[r[71]||=f(`p`,{class:`text-sm font-medium text-textMain mb-2`},`2. 初始化项目配置`,-1),f(`div`,Pn,[f(`code`,Fn,g(wa.value),1),f(`button`,{onClick:r[5]||=e=>Y(`init`,wa.value),class:`text-xs text-primary hover:text-textMain`},g(F.value===`init`?`已复制`:`复制`),1)]),f(`p`,In,[r[65]||=b(`执行后会在当前目录生成 `,-1),f(`code`,Ln,g(Ca.value),1),r[66]||=b(`,请确认生成的配置:`,-1)]),f(`pre`,Rn,g(Ma.value),1),f(`div`,zn,[r[67]||=f(`p`,null,[f(`code`,{class:`font-mono text-textMain`},`projectId`),b(` — 项目唯一标识,由服务端分配`)],-1),r[68]||=f(`p`,null,[f(`code`,{class:`font-mono text-textMain`},`outputDir`),b(` — 本地打包输出目录,默认 `),f(`code`,{class:`font-mono`},`./dist`)],-1),r[69]||=f(`p`,null,[f(`code`,{class:`font-mono text-textMain`},`files`),b(` — 要打包上传的文件 glob 模式列表,示例:`)],-1),f(`div`,Bn,[(e(),m(u,null,a(Na,e=>f(`div`,{key:e.label,class:`flex items-center gap-2`},[f(`span`,Vn,g(e.label),1),f(`code`,Hn,`"files": `+g(JSON.stringify(e.files)),1)])),64))]),r[70]||=f(`p`,null,[f(`code`,{class:`font-mono text-textMain`},`postDeploy`),b(` — 服务端解压后执行的命令,如重启服务`)],-1)])]),f(`div`,Un,[f(`div`,Wn,[r[72]||=f(`p`,{class:`text-sm font-medium text-textMain mb-2`},`3. 部署 — 使用已保存的配置`,-1),f(`div`,Gn,[f(`code`,Kn,g(Ta.value),1),f(`button`,{onClick:r[6]||=e=>Y(`push`,Ta.value),class:`text-xs text-primary hover:text-textMain`},g(F.value===`push`?`已复制`:`复制`),1)]),r[73]||=f(`p`,{class:`text-xs text-textMuted mt-2`},[b(`需先通过 `),f(`code`,{class:`font-mono`},`kite config:set token`),b(` 或 `),f(`code`,{class:`font-mono`},`--token-store global`),b(` 保存过 Token。`)],-1)]),f(`div`,qn,[r[76]||=f(`p`,{class:`text-sm font-medium text-textMain mb-2`},`3. 部署 — CLI 覆盖配置`,-1),f(`div`,Jn,[r[74]||=f(`span`,{class:`text-xs text-textMuted w-20 shrink-0`},`使用全局 Token`,-1),f(`code`,Yn,g(Ea.value),1),f(`button`,{onClick:r[7]||=e=>Y(`direct-push`,Ea.value),class:`text-xs text-primary hover:text-textMain`},g(F.value===`direct-push`?`已复制`:`复制`),1)]),f(`div`,Xn,[r[75]||=f(`span`,{class:`text-xs text-textMuted w-20 shrink-0`},`指定项目 Token`,-1),f(`code`,Zn,g(Da.value),1),f(`button`,{onClick:r[8]||=e=>Y(`direct-push-token`,Da.value),class:`text-xs text-primary hover:text-textMain`},g(F.value===`direct-push-token`?`已复制`:`复制`),1)])])]),f(`div`,Qn,[r[84]||=f(`p`,{class:`text-sm text-textMain leading-relaxed`},[f(`strong`,{class:`text-primary font-medium`},`Token 设置方式`),f(`span`,{class:`text-textMuted`},`(已自动填充本项目 Token,可一键复制):`)],-1),f(`div`,$n,[f(`div`,er,[r[77]||=f(`span`,{class:`text-xs text-textMuted w-28 shrink-0`},`按项目保存`,-1),f(`code`,tr,g(ka.value),1),f(`button`,{onClick:r[9]||=e=>Y(`token-set-project`,ka.value),disabled:!T.value?.token,class:`text-xs text-primary hover:text-textMain disabled:opacity-40 disabled:cursor-not-allowed shrink-0`,title:T.value?.token?`复制命令`:`请先生成 Token`},g(F.value===`token-set-project`?`已复制`:`复制`),9,nr)]),f(`p`,rr,[r[78]||=b(`需在含 `,-1),f(`code`,ir,g(Ca.value),1),r[79]||=b(` 的目录执行,token 会写入 `,-1),r[80]||=f(`code`,{class:`font-mono`},`~/.kite/config.json`,-1),r[81]||=b(` 的项目命名空间。`,-1)]),f(`div`,ar,[r[82]||=f(`span`,{class:`text-xs text-textMuted w-28 shrink-0`},`全局 fallback`,-1),f(`code`,or,g(Aa.value),1),f(`button`,{onClick:r[10]||=e=>Y(`token-set-global`,Aa.value),disabled:!T.value?.token,class:`text-xs text-primary hover:text-textMain disabled:opacity-40 disabled:cursor-not-allowed shrink-0`,title:T.value?.token?`复制命令`:`请先生成 Token`},g(F.value===`token-set-global`?`已复制`:`复制`),9,sr)]),f(`div`,cr,[r[83]||=f(`span`,{class:`text-xs text-textMuted w-28 shrink-0`},`.env.local`,-1),f(`code`,lr,g(ja.value),1),f(`button`,{onClick:r[11]||=e=>Y(`token-env-local`,ja.value),disabled:!T.value?.token,class:`text-xs text-primary hover:text-textMain disabled:opacity-40 disabled:cursor-not-allowed shrink-0`,title:T.value?.token?`复制 .env.local 行`:`请先生成 Token`},g(F.value===`token-env-local`?`已复制`:`复制`),9,ur)])]),T.value?.token?h(``,!0):(e(),m(`p`,dr,` 当前项目尚未生成 Token,请先在上方「项目 Token」区域生成后再复制。 `)),r[85]||=c(`<p class="text-sm text-textMuted leading-relaxed"> 配置优先级:<strong class="text-primary">CLI 参数</strong> > <strong class="text-primary">.env.local</strong> > <strong class="text-primary">项目级 Token</strong> > <strong class="text-primary">全局 Token</strong>。未在 CLI 传入的部署脚本,会回退到本页保存的云端默认脚本。 </p>`,1)])],512),[[ke,!L.value]])])],512),[[ke,$.value===`overview`]]),s(f(`section`,fr,[f(`div`,pr,[f(`div`,mr,[f(`h2`,hr,[x(v(me),{class:`w-5 h-5 mr-2 text-primary`}),r[86]||=b(` 项目基本信息 `,-1)]),r[87]||=f(`p`,{class:`text-sm text-textMuted mt-1`},`项目的分类与标签,用于在项目列表中筛选与归档。`,-1)]),f(`div`,gr,[f(`div`,null,[r[89]||=f(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`所属分类`,-1),s(f(`select`,{"onUpdate:modelValue":r[12]||=e=>D.value.categoryId=e,class:`w-full bg-base border border-border rounded-md px-4 py-3 text-textMain text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`},[r[88]||=f(`option`,{value:``},`默认(未分类)`,-1),(e(!0),m(u,null,a(v(S).categories,t=>(e(),m(`option`,{key:t.id,value:t.id},g(t.name),9,_r))),128))],512),[[je,D.value.categoryId]]),r[90]||=f(`p`,{class:`text-xs text-textMuted mt-2`},`用于在项目列表中按分类筛选。在「项目管理 → 管理分类」中创建更多分类。`,-1)]),f(`div`,null,[r[91]||=f(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`标签(可多选)`,-1),x(De,{"model-value":D.value.tagIds,size:`md`,"read-only-save":``,"aria-label":`编辑当前项目的标签`,"onUpdate:modelValue":r[13]||=e=>D.value.tagIds=e},null,8,[`model-value`]),r[92]||=f(`p`,{class:`text-xs text-textMuted mt-2`},`点击「+ 标签」选择或直接新建;颜色和排序请在「项目管理 → 管理标签」里调整。`,-1)]),f(`div`,vr,[f(`button`,{onClick:Ji,disabled:H.value,class:`flex items-center px-5 py-2 text-sm bg-primary hover:bg-primary/90 text-white rounded-md transition-all font-medium disabled:opacity-50`},[H.value?(e(),_(v(E),{key:0,class:`w-4 h-4 mr-2 animate-spin`})):(e(),_(v(Se),{key:1,class:`w-4 h-4 mr-2`})),b(` `+g(H.value?`保存中...`:`保存基本信息`),1)],8,yr)])])]),f(`div`,br,[f(`div`,xr,[f(`h2`,Sr,[x(v(re),{class:`w-5 h-5 mr-2 text-primary`}),r[93]||=b(` PM2 应用绑定 `,-1)]),r[94]||=f(`p`,{class:`text-sm text-textMuted mt-1`},`将本项目关联到一个 PM2 应用,启用顶部实时资源监控与状态面板;保存后会自动尝试导入该应用的 stdout / stderr 日志源。`,-1)]),f(`div`,Cr,[f(`div`,null,[f(`label`,wr,[r[95]||=b(` PM2 应用名(可选) `,-1),G.value?(e(),m(`span`,Tr,`PM2 已检测`)):(e(),m(`span`,Er,`PM2 未检测`))]),ua.value?(e(),m(`div`,Dr,[f(`button`,{type:`button`,onClick:j(oa,[`stop`]),class:`w-full flex items-center justify-between bg-base border border-border rounded-md px-4 py-3 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`},[f(`span`,{class:p(D.value.pm2AppName.trim()?`text-textMain`:`text-textMuted font-sans`)},g(D.value.pm2AppName.trim()||`从 pm2 list 选择应用…`),3),x(v(fe),{class:p([`w-4 h-4 text-textMuted shrink-0`,J.value?`rotate-180`:``])},null,8,[`class`])]),J.value?(e(),m(`div`,Or,[D.value.pm2AppName.trim()?(e(),m(`button`,{key:0,type:`button`,onClick:r[14]||=j(e=>ca(``),[`stop`]),class:`flex items-center w-full px-3 py-2 text-sm text-textMuted hover:bg-white/5 transition-colors border-b border-border`},[x(v(Ie),{class:`w-3.5 h-3.5 mr-2`}),r[96]||=b(` 解除绑定 `,-1)])):h(``,!0),(e(!0),m(u,null,a(K.value,t=>(e(),m(`button`,{key:t.pmId+`:`+t.name,type:`button`,onClick:j(e=>ca(t.name),[`stop`]),class:`flex items-center justify-between w-full px-3 py-2 text-sm text-textMain hover:bg-white/5 transition-colors`},[f(`span`,Ar,[D.value.pm2AppName.trim()===t.name?(e(),_(v(le),{key:0,class:`w-3.5 h-3.5 mr-2 text-primary shrink-0`})):(e(),m(`span`,jr)),f(`span`,Mr,g(t.name),1)]),f(`span`,Nr,[f(`span`,Pr,`#`+g(t.pmId),1),f(`span`,{class:p([`text-[10px] px-1.5 py-0.5 rounded border`,t.status===`online`?`text-success border-success/40 bg-success/10`:`text-textMuted border-border bg-base`])},g(t.status),3)])],8,kr))),128)),f(`button`,{type:`button`,onClick:j(la,[`stop`]),class:`flex items-center w-full px-3 py-2 text-sm text-textMuted hover:bg-white/5 transition-colors border-t border-border`},[x(v(ue),{class:`w-3.5 h-3.5 mr-2`}),r[97]||=b(` 手动输入… `,-1)])])):h(``,!0)])):(e(),m(`div`,Fr,[s(f(`input`,{"onUpdate:modelValue":r[15]||=e=>D.value.pm2AppName=e,type:`text`,list:`pm2-apps-suggest`,spellcheck:`false`,class:`w-full bg-base border border-border rounded-md px-4 py-3 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`e.g. my-api / web-server`},null,512),[[O,D.value.pm2AppName]]),f(`datalist`,Ir,[(e(!0),m(u,null,a(K.value,t=>(e(),m(`option`,{key:t.pmId+`:`+t.name,value:t.name},null,8,Lr))),128))]),G.value&&K.value.length>0?(e(),m(`button`,{key:0,type:`button`,onClick:r[16]||=e=>aa.value=!1,class:`mt-2 text-xs text-primary hover:text-textMain inline-flex items-center`},[x(v(fe),{class:`w-3.5 h-3.5 mr-1`}),r[98]||=b(` 改用下拉选择 `,-1)])):h(``,!0)])),da.value.length>0?(e(),m(`div`,Rr,[x(v(Me),{class:`w-3.5 h-3.5 mt-0.5 shrink-0`}),f(`div`,zr,[r[99]||=b(` 该 PM2 应用名已被 `,-1),(e(!0),m(u,null,a(da.value,(n,r)=>(e(),m(u,{key:n.id},[x(o,{to:`/projects/${n.id}`,class:`font-medium text-yellow-500 hover:text-yellow-400 underline underline-offset-2 mx-0.5`},{default:t(()=>[b(`「`+g(n.name)+`」`,1)]),_:2},1032,[`to`]),r<da.value.length-1?(e(),m(`span`,Br,`、`)):h(``,!0)],64))),128)),r[100]||=b(` 绑定。继续保存不会被阻止,但状态与日志会同时归属于多个项目,请确认无误后再绑定。 `,-1)])])):h(``,!0),r[101]||=f(`p`,{class:`text-xs text-textMuted mt-2`},[b(` 绑定后,可在页面顶部实时查看该 PM2 应用的资源占用与运行状态。需要服务器上安装 PM2,且当前 Kite 进程可执行 `),f(`code`,{class:`font-mono`},`pm2 jlist`),b(`。 `)],-1)]),f(`div`,Vr,[f(`button`,{onClick:Yi,disabled:U.value,class:`flex items-center px-5 py-2 text-sm bg-primary hover:bg-primary/90 text-white rounded-md transition-all font-medium disabled:opacity-50`},[U.value?(e(),_(v(E),{key:0,class:`w-4 h-4 mr-2 animate-spin`})):(e(),_(v(Se),{key:1,class:`w-4 h-4 mr-2`})),b(` `+g(U.value?`保存中...`:`保存 PM2 绑定`),1)],8,Hr)])])]),f(`div`,Ur,[f(`div`,Wr,[f(`h2`,Gr,[x(v(we),{class:`w-5 h-5 mr-2 text-primary`}),r[102]||=b(` 部署脚本配置 (云端默认) `,-1)]),r[103]||=f(`p`,{class:`text-sm text-textMuted mt-1`},`配置此项目在服务端接收到文件后,默认执行的 Shell 指令。可被 CLI 参数覆盖。`,-1)]),f(`div`,Kr,[f(`div`,null,[r[104]||=f(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`部署目录 (Destination Path)`,-1),s(f(`input`,{"onUpdate:modelValue":r[17]||=e=>D.value.destPath=e,type:`text`,class:`w-full bg-base border border-border rounded-md px-4 py-3 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`e.g. /var/www/my-project`},null,512),[[O,D.value.destPath]]),r[105]||=f(`p`,{class:`text-xs text-textMuted mt-2`},`在服务端解压和部署该项目文件的绝对路径。`,-1)]),f(`div`,null,[r[107]||=f(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`前置脚本 (Pre-Deploy)`,-1),f(`div`,qr,[r[106]||=f(`div`,{class:`absolute left-0 top-0 bottom-0 w-8 bg-base border-r border-border rounded-l-md flex flex-col items-center py-3 text-textMuted font-mono text-xs select-none`},[f(`span`,null,`1`)],-1),s(f(`textarea`,{"onUpdate:modelValue":r[18]||=e=>D.value.preDeploy=e,class:`w-full bg-base border border-border rounded-md pl-11 pr-4 py-3 text-success font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all min-h-[100px] resize-y`,placeholder:`# e.g. npm install && npm run build`,spellcheck:`false`},null,512),[[O,D.value.preDeploy]])]),r[108]||=f(`p`,{class:`text-xs text-textMuted mt-2`},`在打包上传之前,于本地执行的构建命令(通常配置在本地 CLI,此处作为备用参考)。`,-1)]),f(`div`,null,[r[111]||=f(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`后置脚本 (Post-Deploy)`,-1),f(`div`,Jr,[r[109]||=f(`div`,{class:`absolute left-0 top-0 bottom-0 w-8 bg-base border-r border-border rounded-l-md flex flex-col items-center py-3 text-textMuted font-mono text-xs select-none`},[f(`span`,null,`1`)],-1),s(f(`textarea`,{"onUpdate:modelValue":r[19]||=e=>D.value.postDeploy=e,class:`w-full bg-base border border-border rounded-md pl-11 pr-4 py-3 text-success font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all min-h-[100px] resize-y`,placeholder:`# e.g. pm2 restart api-server`,spellcheck:`false`},null,512),[[O,D.value.postDeploy]])]),r[112]||=f(`p`,{class:`text-xs text-textMuted mt-2`},`服务端解压文件后,在目标目录执行的重启或服务加载命令。`,-1),f(`label`,Yr,[s(f(`input`,{"onUpdate:modelValue":r[20]||=e=>D.value.postDeployAsync=e,type:`checkbox`,class:`mt-0.5 w-4 h-4 rounded border-border bg-base text-primary focus:ring-1 focus:ring-primary/50`},null,512),[[Ae,D.value.postDeployAsync]]),r[110]||=c(`<span class="text-xs text-textMuted leading-relaxed"><span class="text-textMain font-medium">异步执行(不等待)</span> — 开启后,postDeploy 触发即认为部署成功;脚本输出仍可在部署日志中查看。适合启动常驻进程 / pm2 restart / 延迟任务。 <span class="text-danger">注意:Kite 进程退出时子进程会被回收,需常驻请配合 <code class="font-mono">nohup</code> / <code class="font-mono">pm2</code> / <code class="font-mono">setsid</code> 自行守护。</span></span>`,1)])]),f(`div`,Xr,[f(`button`,{onClick:Xi,disabled:W.value,class:`flex items-center px-6 py-2.5 bg-primary hover:bg-primary/90 text-white rounded-md transition-all font-medium shadow-[0_0_15px_rgba(59,130,246,0.3)] disabled:opacity-50`},[W.value?(e(),_(v(E),{key:0,class:`w-4 h-4 mr-2 animate-spin`})):(e(),_(v(Se),{key:1,class:`w-4 h-4 mr-2`})),b(` `+g(W.value?`保存中...`:`保存部署脚本`),1)],8,Zr)])])]),f(`div`,Qr,[f(`div`,$r,[f(`h2`,ei,[x(v(He),{class:`w-5 h-5 mr-2 text-primary`}),r[113]||=b(` 部署清理策略 `,-1)]),r[114]||=f(`p`,{class:`text-sm text-textMuted mt-1`},[b(`每次部署解压前,对目标目录执行的清理动作。默认 `),f(`code`,{class:`font-mono text-textMain`},`merge`),b(` 沿用旧行为(零破坏)。`)],-1)]),f(`div`,ti,[f(`div`,ni,[(e(),m(u,null,a([{value:`merge`,title:`merge`,desc:`不清理,直接覆盖。旧行为,零破坏。`,tone:`primary`},{value:`clean`,title:`clean`,desc:`清空目录,但保留 protectPaths 命中的文件,以及 .kite-* 内部目录。`,tone:`warning`},{value:`clean-all`,title:`clean-all`,desc:`清空全部内容(仅保留 .kite-*),protectPaths 也被忽略。`,tone:`danger`}],t=>f(`label`,{key:t.value,class:p([`relative flex flex-col p-4 rounded-lg border-2 cursor-pointer transition-all`,k.value.cleanMode===t.value?t.tone===`danger`?`border-danger bg-danger/5`:t.tone===`warning`?`border-yellow-400 bg-yellow-400/5`:`border-primary bg-primary/5`:`border-border hover:border-textMuted/50 bg-base`])},[s(f(`input`,{type:`radio`,"onUpdate:modelValue":r[21]||=e=>k.value.cleanMode=e,value:t.value,class:`sr-only`},null,8,ri),[[Pe,k.value.cleanMode]]),f(`span`,{class:p([`text-sm font-semibold font-mono`,t.tone===`danger`?`text-danger`:t.tone===`warning`?`text-yellow-400`:`text-primary`])},g(t.title),3),f(`span`,ii,g(t.desc),1),k.value.cleanMode===t.value?(e(),_(v(Le),{key:0,class:p([`absolute top-2 right-2 w-4 h-4`,t.tone===`danger`?`text-danger`:t.tone===`warning`?`text-yellow-400`:`text-primary`])},null,8,[`class`])):h(``,!0)],2)),64))]),k.value.cleanMode===`clean`?(e(),m(`div`,ai,[r[116]||=c(`<label class="block text-sm font-medium text-textMain mb-2">保护路径 (protectPaths)</label><p class="text-xs text-textMuted mb-2"> 支持 minimatch glob,命中文件不会被删除。<code class="font-mono text-textMain">.kite-*</code> 始终自动保护,无需添加。 常见示例:<code class="font-mono text-textMain">uploads/**</code>、<code class="font-mono text-textMain">.env</code>、<code class="font-mono text-textMain">config/*.json</code></p>`,2),f(`div`,oi,[s(f(`input`,{"onUpdate:modelValue":r[22]||=e=>A.value=e,type:`text`,class:`flex-1 bg-base border border-border rounded-md px-3 py-2 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`如 uploads/**`,onKeydown:ze(j(ha,[`prevent`]),[`enter`])},null,40,si),[[O,A.value]]),f(`button`,{onClick:ha,type:`button`,class:`flex items-center px-3 bg-base border border-border hover:border-primary/50 hover:text-primary text-textMain rounded-md transition-all`},[x(v(Te),{class:`w-4 h-4 mr-1`}),r[115]||=b(` 添加 `,-1)])]),k.value.protectPaths.length?(e(),m(`div`,ci,[(e(!0),m(u,null,a(k.value.protectPaths,t=>(e(),m(`span`,{key:t,class:`inline-flex items-center gap-1 text-xs px-2 py-1 rounded bg-success/10 border border-success/30 text-success font-mono`},[b(g(t)+` `,1),f(`button`,{onClick:e=>ga(t),type:`button`,class:`text-success/70 hover:text-danger`},[x(v(Ie),{class:`w-3 h-3`})],8,li)]))),128))])):(e(),m(`p`,ui,`尚未设置保护路径。clean 模式下会清空整个部署目录(仅保留 .kite-*)。`))])):h(``,!0),k.value.cleanMode===`clean-all`?(e(),m(`div`,di,[x(v(Ve),{class:`w-4 h-4 text-danger shrink-0 mt-0.5`}),r[117]||=f(`p`,{class:`text-xs text-danger leading-relaxed`},[b(` clean-all 会清空目标目录下`),f(`strong`,null,`所有`),b(`文件(仅保留 `),f(`code`,{class:`font-mono bg-base px-1 rounded`},`.kite-*`),b(`)。protectPaths 设置在此模式下被忽略。请务必通过预览确认。 `)],-1)])):h(``,!0),f(`div`,fi,[k.value.cleanMode===`merge`?h(``,!0):(e(),m(`button`,{key:0,onClick:ya,type:`button`,class:`flex items-center px-4 py-2 text-sm bg-base border border-border hover:border-yellow-400/50 hover:text-yellow-400 text-textMain rounded-md transition-all`},[x(v(ye),{class:`w-4 h-4 mr-2`}),r[118]||=b(` 预览将删除的文件 (DRY-RUN) `,-1)])),f(`button`,{onClick:va,disabled:M.value,class:p([`flex items-center px-6 py-2.5 text-sm font-medium rounded-md transition-all disabled:opacity-50`,k.value.cleanMode===`clean-all`?`bg-danger text-white hover:bg-danger/90`:`bg-primary text-white hover:bg-primary/90 shadow-[0_0_15px_rgba(59,130,246,0.3)]`])},[x(v(Se),{class:`w-4 h-4 mr-2`}),b(` `+g(M.value?`保存中...`:`保存清理策略`),1)],10,pi)])])])],512),[[ke,$.value===`config`]]),s(f(`section`,mi,[f(`div`,hi,[f(`div`,gi,[f(`h3`,_i,[x(v(Oe),{class:`w-4 h-4 mr-2`}),r[119]||=b(` 危险操作区 `,-1)]),f(`div`,{class:`mt-4 flex items-start justify-between gap-4`},[r[120]||=f(`div`,{class:`text-sm text-textMuted space-y-1`},[f(`p`,null,`删除该项目将同时清空数据库中的项目配置与全部部署历史日志,且不可恢复。`),f(`p`,{class:`text-textMuted/80`},`部署目录中的实际文件不会被删除,需要时请手动清理。`)],-1),f(`button`,{onClick:Va,class:`shrink-0 px-4 py-2 bg-danger/10 hover:bg-danger text-danger hover:text-white border border-danger/20 hover:border-danger rounded-md transition-colors text-sm font-medium`},` 删除项目 `)])])])],512),[[ke,$.value===`integration`]]),Ra.value?(e(),m(`div`,{key:0,class:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm`,onClick:j(Ha,[`self`])},[f(`div`,vi,[f(`div`,yi,[f(`div`,bi,[x(v(Me),{class:`w-5 h-5 text-danger`})]),f(`div`,xi,[r[124]||=f(`h2`,{class:`text-lg font-semibold text-textMain`},`确认删除项目`,-1),f(`p`,Si,[r[121]||=b(` 即将删除项目 `,-1),f(`span`,Ci,g(T.value?.name),1),r[122]||=b(` (`,-1),f(`span`,wi,g(v(w)),1),r[123]||=b(`),此操作不可恢复。 `,-1)])])]),f(`div`,Ti,[f(`div`,Ei,[f(`p`,Di,[x(v(Ie),{class:`w-3.5 h-3.5 mr-1.5`}),r[125]||=b(` 将被永久删除的内容 `,-1)]),r[126]||=f(`ul`,{class:`text-xs text-textMain/90 space-y-1 list-disc list-inside marker:text-danger/60`},[f(`li`,null,`该项目在数据库中的配置(名称、描述、部署目录、部署脚本、Token、环境标识等)`),f(`li`,null,[b(`该项目的`),f(`span`,{class:`font-medium`},`全部部署历史日志`),b(`(部署日志面板中将不再可见)`)])],-1)]),f(`div`,Oi,[f(`p`,ki,[x(v(Le),{class:`w-3.5 h-3.5 mr-1.5`}),r[127]||=b(` 不会被删除的内容 `,-1)]),f(`ul`,Ai,[f(`li`,null,[r[128]||=b(` 部署目录 `,-1),f(`code`,ji,g(T.value?.destPath||`—`),1),r[129]||=b(` 下的所有实际文件 `,-1)]),r[130]||=f(`li`,null,`其他项目的数据、全局设置、Admin Token`,-1),r[131]||=f(`li`,null,[b(`项目源码中的 `),f(`code`,{class:`font-mono text-textMain bg-base px-1 py-0.5 rounded text-[11px]`},`kite.config*.json`),b(` / `),f(`code`,{class:`font-mono text-textMain bg-base px-1 py-0.5 rounded text-[11px]`},`.env.local`),b(` 等本地配置`)],-1)])])]),f(`div`,Mi,[f(`label`,Ni,[r[132]||=b(` 请输入项目名称 `,-1),f(`span`,Pi,g(Q.value),1),r[133]||=b(` 以确认删除 `,-1)]),s(f(`input`,{"onUpdate:modelValue":r[23]||=e=>za.value=e,type:`text`,disabled:X.value,placeholder:Q.value,class:`w-full bg-base border border-border rounded-md px-3 py-2 text-textMain font-mono focus:outline-none focus:border-danger focus:ring-1 focus:ring-danger/50 transition-all text-sm disabled:opacity-60`,onKeydown:ze(j(Ua,[`prevent`]),[`enter`])},null,40,Fi),[[O,za.value]])]),Z.value?(e(),m(`p`,Ii,g(Z.value),1)):h(``,!0),f(`div`,Li,[f(`button`,{onClick:Ha,disabled:X.value,class:`px-4 py-2 text-sm font-medium text-textMuted hover:text-textMain dark:hover:bg-white/5 hover:bg-black/5 rounded-md transition-colors disabled:opacity-50 disabled:cursor-not-allowed`},` 取消 `,8,Ri),f(`button`,{onClick:Ua,disabled:!Ba.value,class:`px-4 py-2 text-sm font-medium bg-danger text-white rounded-md hover:bg-danger/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center`},[X.value?(e(),_(v(E),{key:0,class:`w-4 h-4 mr-2 animate-spin`})):(e(),_(v(Oe),{key:1,class:`w-4 h-4 mr-2`})),b(` `+g(X.value?`正在删除...`:`永久删除`),1)],8,zi)])])])):h(``,!0),x(Be,{open:Pa.value,"onUpdate:open":r[24]||=e=>Pa.value=e,tone:`warning`,title:`重新生成项目 Token?`,message:`旧 Token 将立即失效。所有正在使用旧 Token 的 CLI / Webhook 调用都会被拒绝,请记得同步更新。`,"confirm-text":`重新生成`,"cancel-text":`取消`,loading:Fa.value,onConfirm:La},null,8,[`open`,`loading`]),x(st,{open:We.value,"onUpdate:open":r[25]||=e=>We.value=e,loading:Ge.value,error:Ke.value,preview:qe.value,mode:k.value.cleanMode===`merge`?`clean`:k.value.cleanMode,"protect-paths":k.value.protectPaths},null,8,[`open`,`loading`,`error`,`preview`,`mode`,`protect-paths`]),x(Be,{open:N.value,"onUpdate:open":r[26]||=e=>N.value=e,tone:`danger`,title:`确认启用 clean-all 模式?`,message:`后续每次部署都会清空部署目录下除 .kite-* 之外的全部内容,protectPaths 在此模式下被忽略。请输入项目名以确认。`,"confirm-text":`启用 clean-all`,"cancel-text":`取消`,"require-text":Q.value,"require-text-hint":`请输入项目名 ${Q.value} 以确认`,loading:M.value,onConfirm:_a},null,8,[`open`,`require-text`,`require-text-hint`,`loading`]),x(Be,{open:B.value,"onUpdate:open":r[27]||=e=>B.value=e,tone:`warning`,title:`确认回滚到此版本?`,message:V.value?`将以归档 ${rt(V.value.id)} 重新部署到项目 ${V.value.projectName}。会按当前项目的 cleanMode / protectPaths 执行清理后再解压,运行时数据按保护规则保留。`:``,"confirm-text":`确认回滚`,"cancel-text":`取消`,loading:tt.value,onConfirm:Wi},null,8,[`open`,`message`,`loading`])])):h(``,!0)}}});export{Vi as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.fade-enter-active[data-v-e5333666],.fade-leave-active[data-v-e5333666]{transition:opacity .15s}.fade-enter-from[data-v-e5333666],.fade-leave-to[data-v-e5333666]{opacity:0}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{A as e,B as t,D as n,E as r,M as i,T as a,U as o,V as s,b as ee,c,d as l,f as u,ft as d,h as f,l as te,m as p,mt as m,n as ne,p as h,pt as re,q as g,t as _,v,y,z as ie}from"./createLucideIcon-BmsTm7z-.js";import{t as ae}from"./activity-DZCOq6kQ.js";import{t as oe}from"./FolderPickerDialog-CKohwBIP.js";import{t as se}from"./pencil-BTFuj0gA.js";import{n as ce}from"./file-text-BxWt6is5.js";import{t as le}from"./clock-DIBzfDoY.js";import{t as ue}from"./folder-open-DQz0XviI.js";import{t as de}from"./plus-CcefsCv_.js";import{t as b}from"./refresh-cw-OqaxwQhF.js";import{t as fe}from"./scroll-text-6UwJwqap.js";import{t as pe}from"./server-DFHpqwVn.js";import{a as x,i as me,n as he,r as S,t as ge}from"./ProjectTagsEditor-zXN_5rwP.js";import{t as _e}from"./trash-2-20ikd6fk.js";import{d as ve,g as C,h as ye,i as be,n as xe,o as Se,r as Ce,t as w,u as we,v as T,y as E}from"./index-BZU6i5nw.js";var Te=_(`ellipsis-vertical`,[[`circle`,{cx:`12`,cy:`12`,r:`1`,key:`41hilf`}],[`circle`,{cx:`12`,cy:`5`,r:`1`,key:`gxeob9`}],[`circle`,{cx:`12`,cy:`19`,r:`1`,key:`lyex9k`}]]),Ee=_(`folder-plus`,[[`path`,{d:`M12 10v6`,key:`1bos4e`}],[`path`,{d:`M9 13h6`,key:`1uhe8q`}],[`path`,{d:`M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z`,key:`1kt360`}]]),De=_(`folder-tree`,[[`path`,{d:`M20 10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-2.5a1 1 0 0 1-.8-.4l-.9-1.2A1 1 0 0 0 15 3h-2a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z`,key:`hod4my`}],[`path`,{d:`M20 21a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1h-2.9a1 1 0 0 1-.88-.55l-.42-.85a1 1 0 0 0-.92-.6H13a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z`,key:`w4yl2u`}],[`path`,{d:`M3 5a2 2 0 0 0 2 2h3`,key:`f2jnh7`}],[`path`,{d:`M3 3v13a2 2 0 0 0 2 2h3`,key:`k8epm1`}]]),Oe=_(`layout-grid`,[[`rect`,{width:`7`,height:`7`,x:`3`,y:`3`,rx:`1`,key:`1g98yp`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`3`,rx:`1`,key:`6d4xhi`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`14`,rx:`1`,key:`nxv5o0`}],[`rect`,{width:`7`,height:`7`,x:`3`,y:`14`,rx:`1`,key:`1bb6yr`}]]),ke=_(`list`,[[`path`,{d:`M3 5h.01`,key:`18ugdj`}],[`path`,{d:`M3 12h.01`,key:`nlz23k`}],[`path`,{d:`M3 19h.01`,key:`noohij`}],[`path`,{d:`M8 5h13`,key:`1pao27`}],[`path`,{d:`M8 12h13`,key:`1za7za`}],[`path`,{d:`M8 19h13`,key:`m83p4d`}]]),Ae=_(`tags`,[[`path`,{d:`M13.172 2a2 2 0 0 1 1.414.586l6.71 6.71a2.4 2.4 0 0 1 0 3.408l-4.592 4.592a2.4 2.4 0 0 1-3.408 0l-6.71-6.71A2 2 0 0 1 6 9.172V3a1 1 0 0 1 1-1z`,key:`16rjxf`}],[`path`,{d:`M2 7v6.172a2 2 0 0 0 .586 1.414l6.71 6.71a2.4 2.4 0 0 0 3.191.193`,key:`178nd4`}],[`circle`,{cx:`10.5`,cy:`6.5`,r:`.5`,fill:`currentColor`,key:`12ikhr`}]]),je={class:`max-w-7xl mx-auto space-y-6`},Me={class:`flex flex-col md:flex-row md:justify-between md:items-center gap-3 mb-8`},Ne={class:`flex items-center flex-wrap gap-2`},Pe={class:`flex items-center border border-border rounded-md overflow-hidden`},Fe={class:`flex items-center flex-wrap gap-2`},Ie={class:`ml-1.5 text-[10px] opacity-75`},Le={class:`ml-1.5 text-[10px] opacity-75`},Re=[`onClick`],ze={class:`ml-1.5 text-[10px] opacity-75`},Be={key:0,class:`flex items-center flex-wrap gap-2`},Ve={class:`ml-1.5 text-[10px] opacity-75`},He={class:`ml-1.5 text-[10px] opacity-75`},Ue=[`onClick`],We={class:`ml-1.5 text-[10px] opacity-75 font-sans`},Ge={key:1,class:`flex items-center flex-wrap gap-2`},Ke=[`onClick`,`title`],qe={key:0,class:`ml-1.5 text-[10px] opacity-75`},Je={key:2,class:`grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-6`},Ye=[`onClick`],Xe={class:`flex justify-between items-start mb-4`},Ze={class:`flex items-center space-x-3`},Qe={class:`p-2 rounded-lg bg-base border border-border group-hover:border-primary/30 transition-colors`},$e={class:`font-semibold text-textMain text-base`},et={class:`text-xs text-textMuted font-mono mt-0.5`},tt={class:`relative`},nt=[`onClick`],rt={class:`text-sm text-textMuted mb-3 line-clamp-2 min-h-[40px]`},it={class:`flex items-center flex-wrap gap-1.5 mb-3`},at={class:`flex items-center justify-between border-t border-border pt-4 text-xs text-textMuted`},ot=[`title`],st={class:`flex items-center space-x-3`},ct=[`onClick`],lt=[`onClick`],ut={key:0,class:`col-span-full text-center py-16 text-textMuted text-sm`},dt={key:3,class:`bg-panel border border-border rounded-xl overflow-hidden`},ft={class:`overflow-x-auto`},pt={class:`w-full text-sm min-w-[720px]`},mt=[`onClick`],ht={class:`px-4 py-3`},gt={class:`flex items-center space-x-2`},_t={class:`text-textMain font-medium`},vt={class:`text-[11px] text-textMuted font-mono`},yt={class:`px-4 py-3 text-textMuted font-mono text-xs break-all max-w-xs`},bt={class:`px-4 py-3`},xt={class:`flex items-center flex-wrap gap-1`},St={class:`px-4 py-3`},Ct={key:1,class:`text-textMuted text-xs`},wt=[`title`],Tt={class:`px-4 py-3`},Et={class:`px-4 py-3 text-right`},Dt=[`onClick`],Ot={key:0},kt={class:`relative`},At={class:`flex items-center`},jt=[`disabled`],Mt=[`disabled`,`onClick`],Nt={key:0,class:`px-3 py-2 text-xs text-textMuted`},Pt={key:4,class:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`},Ft={class:`bg-panel border border-border rounded-xl w-full max-w-md p-6 shadow-2xl transform transition-all max-h-[90vh] overflow-y-auto`},It={class:`space-y-4`},Lt=[`value`],Rt={key:0,class:`text-xs text-textMuted`},zt={key:1,class:`flex items-center flex-wrap gap-1.5`},Bt=[`onClick`],Vt={class:`mt-8 flex justify-end space-x-3`},Ht=[`disabled`],Ut={class:`bg-panel border border-border rounded-xl w-full max-w-6xl shadow-2xl flex flex-col`,style:{"max-height":`85vh`}},Wt={class:`flex items-center justify-between px-6 py-4 border-b border-border`},Gt={class:`text-xs text-textMuted mt-1`},Kt=[`disabled`],qt={class:`px-6 py-3 border-b border-border bg-yellow-400/15 dark:bg-yellow-400/5 flex items-start space-x-2`},Jt={class:`flex-1 overflow-auto px-2`},Yt={class:`w-full text-sm table-fixed`},Xt={class:`px-3 py-2`},Zt=[`onUpdate:modelValue`,`disabled`],Qt={key:0,class:`text-[11px] text-danger mt-1`},$t={class:`px-3 py-2`},en=[`onUpdate:modelValue`,`disabled`,`title`],tn={key:0,class:`text-[11px] text-danger mt-1`},nn={key:1,class:`text-[11px] text-danger mt-1 break-all`},rn={class:`px-3 py-2`},an=[`onUpdate:modelValue`,`disabled`],on={class:`px-3 py-2`},sn=[`onUpdate:modelValue`,`disabled`],cn=[`value`],ln={class:`px-3 py-2`},un={key:0,class:`text-[11px] text-textMuted`},dn={key:1,class:`flex items-center flex-wrap gap-1`},fn=[`disabled`,`onClick`],pn={class:`px-3 py-2`},mn={class:`flex items-start gap-2`},hn=[`onUpdate:modelValue`,`disabled`],gn=[`onClick`,`disabled`],_n={key:0},vn={class:`flex items-center justify-between px-6 py-4 border-t border-border`},yn={class:`flex items-center space-x-3`},bn=[`disabled`],xn={class:`text-xs text-textMuted`},Sn={class:`flex items-center space-x-2`},Cn=[`disabled`],wn=[`disabled`],Tn={class:`bg-panel border border-border rounded-xl w-full max-w-md p-6 shadow-2xl max-h-[90vh] overflow-y-auto`},En=[`disabled`,`onKeydown`],Dn={class:`mt-6 flex justify-end space-x-3`},On=[`disabled`],kn=[`disabled`],An={class:`bg-panel border border-danger/30 rounded-xl w-full max-w-lg p-6 shadow-2xl max-h-[90vh] overflow-y-auto`},jn={class:`flex items-start space-x-3 mb-5`},Mn={class:`p-2 rounded-lg bg-danger/10 border border-danger/20 shrink-0`},Nn={class:`text-sm text-textMuted mt-1`},Pn={class:`font-mono text-textMain`},Fn={class:`mb-4`},In={class:`block text-sm font-medium text-textMuted mb-1.5`},Ln={class:`font-mono text-textMain`},Rn=[`disabled`,`placeholder`,`onKeydown`],zn={class:`flex justify-end space-x-3`},Bn=[`disabled`],Vn=[`disabled`],Hn={class:`bg-panel border border-border rounded-xl w-full max-w-2xl shadow-2xl flex flex-col`,style:{"max-height":`85vh`}},Un={class:`flex items-center justify-between px-6 py-4 border-b border-border`},Wn={class:`px-6 py-4 border-b border-border`},Gn={class:`flex items-center gap-2`},Kn=[`disabled`,`onKeydown`],qn=[`disabled`],Jn={class:`flex-1 overflow-auto px-6 py-4`},Yn={key:0,class:`text-center py-8 text-textMuted text-sm`},Xn={key:1,class:`divide-y divide-border`},Zn=[`disabled`,`onKeydown`],Qn=[`disabled`],$n=[`disabled`],er={class:`text-xs text-textMuted flex-1`},tr=[`onClick`],nr=[`onClick`,`disabled`],rr={class:`flex items-center justify-end px-6 py-4 border-t border-border`},ir={class:`bg-panel border border-border rounded-xl w-full max-w-2xl shadow-2xl flex flex-col`,style:{"max-height":`85vh`}},ar={class:`flex items-center justify-between px-6 py-4 border-b border-border`},or={class:`px-6 py-4 border-b border-border`},sr={class:`flex items-center gap-2`},cr=[`disabled`,`onKeydown`],lr=[`disabled`],ur={class:`flex-1 overflow-auto px-6 py-4`},dr={key:0,class:`text-center py-8 text-textMuted text-sm`},fr={key:1,class:`divide-y divide-border`},pr=[`disabled`,`onKeydown`],mr=[`disabled`],hr=[`disabled`],gr={class:`flex items-center gap-1`},_r=[`title`,`onClick`],vr={class:`text-xs text-textMuted flex-1 min-w-[60px]`},yr=[`onClick`],br=[`onClick`,`disabled`],xr={class:`flex items-center justify-end px-6 py-4 border-t border-border`},Sr=`kite:projectList:viewMode`,Cr=160,wr=196,D=w(ee({__name:`ProjectList`,setup(ee){let _=ne(),w=we(),D=xe(),O=o(localStorage.getItem(Sr)===`list`?`list`:`card`);ie(O,e=>localStorage.setItem(Sr,e));let k=o(`all`),A=o(`all`),j=o([]);n(()=>{_.fetchProjects(),_.fetchCategories(),_.fetchTags()});let Tr=l(()=>{let e=new Map;for(let t of _.categories)e.set(t.id,t);return e}),Er=l(()=>{let e=_.projects,t=j.value;return e.filter(e=>{if(k.value===`default`){if(e.categoryId)return!1}else if(k.value!==`all`&&e.categoryId!==k.value)return!1;let n=(e.env||``).trim();if(A.value===`default`){if(n)return!1}else if(A.value!==`all`&&n!==A.value)return!1;if(t.length>0){let n=e.tagIds||[];for(let e of t)if(!n.includes(e))return!1}return!0})}),Dr=l(()=>{let e={all:_.projects.length,default:0};for(let t of _.categories)e[t.id]=0;for(let t of _.projects)!t.categoryId||!e.hasOwnProperty(t.categoryId)?e.default++:e[t.categoryId]++;return e}),Or=l(()=>{let e=new Set;for(let t of _.projects){let n=(t.env||``).trim();n&&e.add(n)}return Array.from(e).sort((e,t)=>e.localeCompare(t))}),M=l(()=>{let e={all:_.projects.length,default:0};for(let t of Or.value)e[t]=0;for(let t of _.projects){let n=(t.env||``).trim();n?e[n]=(e[n]||0)+1:e.default++}return e});ie([Or,M],()=>{let e=A.value;if(e!==`all`){if(e===`default`){M.value.default===0&&(A.value=`all`);return}Or.value.includes(e)||(A.value=`all`)}});let kr={blue:`bg-blue-500/15 text-blue-500 border-blue-500/30`,green:`bg-green-500/15 text-green-500 border-green-500/30`,yellow:`bg-yellow-500/15 text-yellow-500 border-yellow-500/30`,purple:`bg-purple-500/15 text-purple-500 border-purple-500/30`,pink:`bg-pink-500/15 text-pink-500 border-pink-500/30`,cyan:`bg-cyan-500/15 text-cyan-500 border-cyan-500/30`,gray:`bg-gray-500/15 text-gray-400 border-gray-500/30`};function Ar(e){return e&&kr[e]?kr[e]:`bg-base text-textMuted border-border`}let jr=[`blue`,`green`,`yellow`,`purple`,`pink`,`cyan`,`gray`];function Mr(e){let t=(e||``).trim().toLowerCase();if(!t)return`bg-base text-textMuted border-border`;let n=0;for(let e=0;e<t.length;e++)n=n*31+t.charCodeAt(e)>>>0;return kr[jr[n%jr.length]]}function Nr(e){return e?Tr.value.get(e)?.name??`默认`:`默认`}function Pr(e){if(!e)return`从未部署`;let t=new Date(e).getTime();if(isNaN(t))return`—`;let n=Date.now()-t,r=Math.floor(n/1e3);if(r<60)return`${r} 秒前`;let i=Math.floor(r/60);if(i<60)return`${i} 分钟前`;let a=Math.floor(i/60);if(a<24)return`${a} 小时前`;let o=Math.floor(a/24);return o<30?`${o} 天前`:new Date(e).toLocaleDateString()}let Fr=o(!1),N=o({name:``,description:``,destPath:``,env:``,categoryId:``,tagIds:[]}),Ir=async()=>{if(!N.value.name||!N.value.destPath)return;let e=await _.addProject({name:N.value.name,description:N.value.description,destPath:N.value.destPath,env:N.value.env,categoryId:N.value.categoryId||null,tagIds:N.value.tagIds.length>0?[...N.value.tagIds]:void 0});if(e.ok)Fr.value=!1,N.value={name:``,description:``,destPath:``,env:``,categoryId:``,tagIds:[]},D.success(`项目创建成功`);else{let t=e.conflictProject?`部署目录已被项目「${e.conflictProject}」占用`:e.error||`请稍后重试`;D.error(`创建失败`,t)}},Lr=e=>{w.push(`/projects/${e}`)},Rr=e=>{w.push({path:`/logs`,query:{projectId:e}})},zr=e=>{w.push(`/projects/${e}/logs`)},Br=e=>{w.push(`/projects/${e}/files`)},P=o(null),Vr=o({});async function Hr(e,t){if(t.stopPropagation(),P.value===e){P.value=null;return}let n=t.currentTarget.getBoundingClientRect(),r=window.innerHeight,i=window.innerWidth,o=r-n.bottom<wr+12&&n.top>wr+12?Math.max(8,n.top-wr-4):Math.min(r-wr-8,n.bottom+4),s=Math.min(i-Cr-8,Math.max(8,n.right-Cr));Vr.value={position:`fixed`,top:`${o}px`,left:`${s}px`,width:`${Cr}px`},P.value=e,await a()}function F(){P.value=null,fi.value=!1}function Ur(){P.value&&F()}n(()=>{window.addEventListener(`scroll`,Ur,!0),window.addEventListener(`resize`,Ur)}),r(()=>{window.removeEventListener(`scroll`,Ur,!0),window.removeEventListener(`resize`,Ur)});let I=o(!1),L=o(null),R=o(``),z=o(!1);function Wr(e,t){F(),L.value={id:e,name:t},R.value=t,I.value=!0}async function Gr(){if(!L.value)return;let e=R.value.trim();if(!e||e===L.value.name){I.value=!1;return}z.value=!0;try{await _.updateProject(L.value.id,{name:e}),D.success(`重命名成功`),I.value=!1}catch(e){D.error(`重命名失败`,e?.message||`请稍后重试`)}finally{z.value=!1}}let B=o(!1),V=o(null),Kr=o(``),H=o(!1);function qr(e,t){F(),V.value={id:e,name:t},Kr.value=``,B.value=!0}let Jr=l(()=>V.value&&Kr.value.trim()===V.value.name&&!H.value);async function Yr(){if(!(!V.value||!Jr.value)){H.value=!0;try{await _.removeProject(V.value.id)?(D.success(`项目已删除`),B.value=!1):D.error(`删除失败`)}catch(e){D.error(`删除失败`,e?.message||`请稍后重试`)}finally{H.value=!1}}}let Xr=o(!1),Zr=o(!1),U=o(!1),W=o([]),Qr=0;function $r(e){let t=e.replace(/[\\/]+$/,``),n=t.split(/[\\/]/);return n[n.length-1]||t||`project`}function ei(){Xr.value=!0}function ti(e){W.value=e.map(e=>({id:++Qr,name:$r(e),destPath:e,env:``,description:``,categoryId:k.value&&k.value!==`all`&&k.value!==`default`?k.value:``,tagIds:j.value.length>0?[...j.value]:[],status:`pending`})),Zr.value=!0,_.fetchCategories(),_.fetchTags()}function ni(e){let t=new Set(W.value.map(e=>e.destPath));for(let n of e)t.has(n)||W.value.push({id:++Qr,name:$r(n),destPath:n,env:``,description:``,categoryId:``,tagIds:[],status:`pending`})}let ri=o(!1);function ii(){ri.value=!0,Xr.value=!0}function ai(e){ri.value?(ni(e),ri.value=!1):ti(e)}function oi(e){W.value=W.value.filter(t=>t.id!==e)}let si=l(()=>new Set(_.projects.map(e=>e.name))),ci=l(()=>new Set(_.projects.map(e=>e.destPath).filter(Boolean))),G=l(()=>{let e=new Map,t=new Map,n=new Map;for(let r of W.value){let i={},a=r.name.trim();a?si.value.has(a)?i.name=`与已有项目重名`:e.has(a)?i.name=`本次批量内重名`:e.set(a,r.id):i.name=`项目名不能为空`;let o=r.destPath.trim();o?ci.value.has(o)?i.dest=`该部署目录已被其他项目占用`:t.has(o)?i.dest=`本次批量内部署目录重复`:t.set(o,r.id):i.dest=`部署目录不能为空`,(i.name||i.dest)&&n.set(r.id,i)}return n}),li=l(()=>!(W.value.length===0||U.value||G.value.size>0)),K=l(()=>{let e=0,t=0,n=0;for(let r of W.value)r.status===`success`?e++:r.status===`failed`?t++:n++;return{success:e,failed:t,pending:n,total:W.value.length}});async function ui(){if(li.value){U.value=!0;try{for(let e of W.value){if(e.status===`success`)continue;e.status=`submitting`,e.errorMsg=void 0;let t=await _.addProject({name:e.name.trim(),description:e.description?.trim()||void 0,destPath:e.destPath,env:e.env?.trim()||void 0,categoryId:e.categoryId||null,tagIds:e.tagIds.length>0?[...e.tagIds]:void 0});t.ok?e.status=`success`:(e.status=`failed`,e.errorMsg=t.conflictProject?`部署目录已被项目「${t.conflictProject}」占用`:t.error||`创建失败`)}let{success:e,failed:t}=K.value;t===0?(D.success(`批量创建完成`,`成功 ${e} 个`),W.value=[],Zr.value=!1):D.error(`部分创建失败`,`成功 ${e} 个,失败 ${t} 个`)}finally{U.value=!1}}}function di(){U.value||(Zr.value=!1,W.value=[])}let fi=o(!1),pi=o(!1);function mi(e){e.stopPropagation(),fi.value=!fi.value}async function hi(e,t){if(!pi.value){pi.value=!0;try{await _.updateProject(e,{categoryId:t});let n=t?Tr.value.get(t)?.name??`分类`:`默认`;D.success(`已移动到「${n}」`),fi.value=!1,F()}catch(e){D.error(`移动失败`,e?.message||`请稍后重试`)}finally{pi.value=!1}}}let gi=o(!1),q=o(``),_i=o(!1),J=o(null),Y=o(``),vi=o(!1),yi=o(null),bi=[`blue`,`green`,`yellow`,`purple`,`pink`,`cyan`,`gray`];function xi(e){let t=new Set;for(let n of _.categories)e&&n.id===e||n.color&&t.add(n.color);for(let e of bi)if(!t.has(e))return e;return bi[_.categories.length%bi.length]}function Si(){gi.value=!0,q.value=``,J.value=null,_.fetchCategories()}async function Ci(){let e=q.value.trim();if(e){_i.value=!0;try{let t=await _.createCategory({name:e,color:xi()});t.ok?(D.success(`分类创建成功`),q.value=``):D.error(`创建失败`,t.conflictCategory?`分类名「${t.conflictCategory}」已存在`:t.error||`请稍后重试`)}finally{_i.value=!1}}}function wi(e){J.value=e.id,Y.value=e.name}function Ti(){J.value=null,Y.value=``}async function Ei(){if(!J.value)return;let e=Y.value.trim();if(e){vi.value=!0;try{let t=await _.updateCategory(J.value,{name:e});t.ok?(D.success(`分类已更新`),Ti()):D.error(`更新失败`,t.conflictCategory?`分类名「${t.conflictCategory}」已存在`:t.error||`请稍后重试`)}finally{vi.value=!1}}}async function Di(e){if(yi.value)return;let t=Dr.value[e.id]||0;if(window.confirm(t>0?`分类「${e.name}」下还有 ${t} 个项目,删除后这些项目会回落到默认。是否继续?`:`确认删除分类「${e.name}」?`)){yi.value=e.id;try{let t=await _.deleteCategory(e.id);t.ok?(D.success(`分类已删除`,t.detachedProjects?`${t.detachedProjects} 个项目已回落到默认`:void 0),k.value===e.id&&(k.value=`all`)):D.error(`删除失败`,t.error||`请稍后重试`)}finally{yi.value=null}}}function Oi(e){j.value.indexOf(e)===-1?j.value=[...j.value,e]:j.value=j.value.filter(t=>t!==e)}function ki(){j.value=[]}async function Ai(e,t){let n=_.projects.find(t=>t.id===e);n&&(n.tagIds=[...t]);try{await _.updateProject(e,{tagIds:[...t]})}catch(e){D.error(`保存标签失败`,e?.message||`请稍后重试`)}}function ji(e,t){e.tagIds.indexOf(t)===-1?e.tagIds=[...e.tagIds,t]:e.tagIds=e.tagIds.filter(e=>e!==t)}let Mi=o(!1),X=o(``),Ni=o(!1),Z=o(null),Q=o(``),Pi=o(!1),$=o(null);function Fi(){Mi.value=!0,X.value=``,Z.value=null,_.fetchTags()}async function Ii(){let e=X.value.trim();if(e){Ni.value=!0;try{let t=me(_.tags),n=await _.createTag({name:e,color:t});n.ok?(D.success(`标签创建成功`),X.value=``):D.error(`创建失败`,n.conflictTag?`标签名「${n.conflictTag}」已存在`:n.error||`请稍后重试`)}finally{Ni.value=!1}}}function Li(e){Z.value=e.id,Q.value=e.name}function Ri(){Z.value=null,Q.value=``}async function zi(){if(!Z.value)return;let e=Q.value.trim();if(e){Pi.value=!0;try{let t=await _.updateTag(Z.value,{name:e});t.ok?(D.success(`标签已更新`),Ri()):D.error(`更新失败`,t.conflictTag?`标签名「${t.conflictTag}」已存在`:t.error||`请稍后重试`)}finally{Pi.value=!1}}}async function Bi(e,t){let n=await _.updateTag(e.id,{color:t});n.ok||D.error(`更新失败`,n.error||`请稍后重试`)}async function Vi(e){if($.value)return;let t=e.projectCount||0;if(window.confirm(t>0?`标签「${e.name}」当前关联了 ${t} 个项目,删除后这些关联会被解除。是否继续?`:`确认删除标签「${e.name}」?`)){$.value=e.id;try{let t=await _.deleteTag(e.id);t.ok?(D.success(`标签已删除`,t.detachedProjects?`${t.detachedProjects} 个项目已解除关联`:void 0),j.value=j.value.filter(t=>t!==e.id)):D.error(`删除失败`,t.error||`请稍后重试`)}finally{$.value=null}}}return(n,r)=>(e(),f(`div`,je,[u(`div`,Me,[r[43]||=u(`div`,null,[u(`h1`,{class:`text-2xl font-bold text-textMain tracking-tight`},`项目管理`),u(`p`,{class:`text-textMuted text-sm mt-1`},`管理所有可部署的应用服务与脚本配置`)],-1),u(`div`,Ne,[u(`div`,Pe,[u(`button`,{onClick:r[0]||=e=>O.value=`card`,class:d([O.value===`card`?`bg-primary/15 text-primary`:`text-textMuted hover:text-textMain`,`flex items-center px-2.5 py-1.5 text-xs transition-colors`]),title:`卡片视图`},[y(g(Oe),{class:`w-3.5 h-3.5`})],2),u(`button`,{onClick:r[1]||=e=>O.value=`list`,class:d([O.value===`list`?`bg-primary/15 text-primary`:`text-textMuted hover:text-textMain`,`flex items-center px-2.5 py-1.5 text-xs transition-colors border-l border-border`]),title:`列表视图`},[y(g(ke),{class:`w-3.5 h-3.5`})],2)]),u(`button`,{onClick:Si,class:`flex items-center px-3 py-2 border border-border hover:border-primary/50 text-textMain rounded-md transition-all font-medium text-sm`,title:`管理分类`},[y(g(De),{class:`w-4 h-4 mr-2`}),r[39]||=v(` 管理分类 `,-1)]),u(`button`,{onClick:Fi,class:`flex items-center px-3 py-2 border border-border hover:border-primary/50 text-textMain rounded-md transition-all font-medium text-sm`,title:`管理标签`},[y(g(Ae),{class:`w-4 h-4 mr-2`}),r[40]||=v(` 管理标签 `,-1)]),u(`button`,{onClick:ei,class:`flex items-center px-4 py-2 bg-primary hover:bg-primary/90 text-white rounded-md shadow-[0_0_15px_rgba(59,130,246,0.3)] transition-all font-medium text-sm`},[y(g(Ee),{class:`w-4 h-4 mr-2`}),r[41]||=v(` 选择文件夹新建 `,-1)]),u(`button`,{onClick:r[2]||=e=>Fr.value=!0,class:`flex items-center px-4 py-2 border border-border hover:border-primary/50 text-textMain rounded-md transition-all font-medium text-sm`},[y(g(de),{class:`w-4 h-4 mr-2`}),r[42]||=v(` 新建项目 `,-1)])])]),u(`div`,Fe,[r[46]||=u(`span`,{class:`text-xs text-textMuted/80 mr-1 shrink-0`},`分类`,-1),u(`button`,{onClick:r[3]||=e=>k.value=`all`,class:d([`flex items-center px-3 py-1.5 rounded-full text-xs border transition-colors`,k.value===`all`?`bg-primary/15 text-primary border-primary/40`:`bg-base text-textMuted border-border hover:text-textMain`])},[r[44]||=v(` 全部 `,-1),u(`span`,Ie,m(Dr.value.all),1)],2),u(`button`,{onClick:r[4]||=e=>k.value=`default`,class:d([`flex items-center px-3 py-1.5 rounded-full text-xs border transition-colors`,k.value===`default`?`bg-primary/15 text-primary border-primary/40`:`bg-base text-textMuted border-border hover:text-textMain`])},[r[45]||=v(` 默认 `,-1),u(`span`,Le,m(Dr.value.default),1)],2),(e(!0),f(c,null,i(g(_).categories,t=>(e(),f(`button`,{key:t.id,onClick:e=>k.value=t.id,class:d([`flex items-center px-3 py-1.5 rounded-full text-xs border transition-colors`,k.value===t.id?`bg-primary/15 text-primary border-primary/40`:`${Ar(t.color)} hover:opacity-90`])},[y(g(x),{class:`w-3 h-3 mr-1.5`}),v(` `+m(t.name)+` `,1),u(`span`,ze,m(Dr.value[t.id]||0),1)],10,Re))),128))]),Or.value.length>0?(e(),f(`div`,Be,[r[49]||=u(`span`,{class:`text-xs text-textMuted/80 mr-1 shrink-0`},`环境`,-1),u(`button`,{onClick:r[5]||=e=>A.value=`all`,class:d([`flex items-center px-3 py-1.5 rounded-full text-xs border transition-colors`,A.value===`all`?`bg-primary/15 text-primary border-primary/40`:`bg-base text-textMuted border-border hover:text-textMain`])},[r[47]||=v(` 全部 `,-1),u(`span`,Ve,m(M.value.all),1)],2),M.value.default>0?(e(),f(`button`,{key:0,onClick:r[6]||=e=>A.value=`default`,class:d([`flex items-center px-3 py-1.5 rounded-full text-xs border transition-colors`,A.value===`default`?`bg-primary/15 text-primary border-primary/40`:`bg-base text-textMuted border-border hover:text-textMain`]),title:`未指定环境的项目`},[r[48]||=v(` 未指定 `,-1),u(`span`,He,m(M.value.default),1)],2)):p(``,!0),(e(!0),f(c,null,i(Or.value,t=>(e(),f(`button`,{key:t,onClick:e=>A.value=t,class:d([`flex items-center px-3 py-1.5 rounded-full text-xs border transition-colors font-mono`,A.value===t?`bg-primary/15 text-primary border-primary/40`:`${Mr(t)} hover:opacity-90`])},[v(m(t)+` `,1),u(`span`,We,m(M.value[t]||0),1)],10,Ue))),128))])):p(``,!0),g(_).tags.length>0?(e(),f(`div`,Ge,[r[51]||=u(`span`,{class:`text-xs text-textMuted/80 mr-1 shrink-0`},`标签`,-1),(e(!0),f(c,null,i(g(_).tags,t=>(e(),f(`button`,{key:t.id,onClick:e=>Oi(t.id),class:d([`flex items-center px-3 py-1.5 rounded-full text-xs border transition-colors`,j.value.includes(t.id)?`${g(S)(t.color)} ring-1 ring-primary/40`:`bg-base text-textMuted border-border hover:text-textMain hover:border-textMuted/40`]),title:j.value.includes(t.id)?`点击取消该标签筛选`:`点击叠加该标签筛选(多选为「与」逻辑)`},[y(g(x),{class:`w-3 h-3 mr-1.5`}),v(` `+m(t.name)+` `,1),t.projectCount==null?p(``,!0):(e(),f(`span`,qe,m(t.projectCount),1))],10,Ke))),128)),j.value.length>0?(e(),f(`button`,{key:0,onClick:ki,class:`flex items-center px-2 py-1.5 rounded-full text-[11px] text-textMuted hover:text-textMain transition-colors`,title:`清空标签筛选`},[y(g(Ce),{class:`w-3 h-3 mr-1`}),r[50]||=v(` 清空 `,-1)])):p(``,!0)])):p(``,!0),O.value===`card`?(e(),f(`div`,Je,[(e(!0),f(c,null,i(Er.value,t=>(e(),f(`div`,{key:t.id,class:`group bg-panel border border-border rounded-xl p-5 hover:border-primary/50 transition-all shadow-sm cursor-pointer relative overflow-hidden`,onClick:e=>Lr(t.id)},[u(`div`,{class:d([`absolute top-0 left-0 w-1 h-full`,t.status===`success`?`bg-success`:t.status===`failed`?`bg-danger`:`bg-primary`])},null,2),u(`div`,Xe,[u(`div`,Ze,[u(`div`,Qe,[y(g(pe),{class:`w-5 h-5 text-textMain group-hover:text-primary transition-colors`})]),u(`div`,null,[u(`h3`,$e,m(t.name),1),u(`p`,et,m(t.id),1)])]),u(`div`,tt,[u(`button`,{class:`p-1 dark:hover:bg-white/10 hover:bg-black/10 rounded-md transition-colors text-textMuted hover:text-textMain`,onClick:E(e=>Hr(t.id,e),[`stop`])},[y(g(Te),{class:`w-4 h-4`})],8,nt)])]),u(`p`,rt,m(t.description||`暂无描述`),1),u(`div`,it,[u(`span`,{class:d([`inline-flex items-center px-2 py-0.5 rounded text-[10px] border`,Ar(Tr.value.get(t.categoryId||``)?.color)])},[y(g(x),{class:`w-3 h-3 mr-1`}),v(` `+m(Nr(t.categoryId)),1)],2),t.env?(e(),f(`span`,{key:0,class:d([`inline-flex items-center px-2 py-0.5 rounded text-[10px] border font-mono`,Mr(t.env)])},m(t.env),3)):p(``,!0),y(ge,{"model-value":t.tagIds||[],size:`sm`,"on-persist":e=>Ai(t.id,e),"aria-label":`编辑「${t.name}」的标签`},null,8,[`model-value`,`on-persist`,`aria-label`])]),u(`div`,at,[u(`div`,{class:`flex items-center`,title:t.lastDeployAt?new Date(t.lastDeployAt).toLocaleString():`从未部署`},[y(g(le),{class:`w-3.5 h-3.5 mr-1.5`}),u(`span`,null,m(Pr(t.lastDeployAt)),1)],8,ot),u(`div`,st,[u(`button`,{onClick:E(e=>Rr(t.id),[`stop`]),class:`flex items-center text-textMuted hover:text-primary transition-colors`,title:`查看部署日志`},[y(g(fe),{class:`w-3.5 h-3.5 mr-1`}),r[52]||=u(`span`,null,`部署日志`,-1)],8,ct),u(`button`,{onClick:E(e=>zr(t.id),[`stop`]),class:`flex items-center text-textMuted hover:text-primary transition-colors`,title:`查看运行日志`},[y(g(ae),{class:`w-3.5 h-3.5 mr-1`}),r[53]||=u(`span`,null,`运行日志`,-1)],8,lt),u(`span`,{class:d([`flex items-center`,t.status===`success`?`text-success`:t.status===`failed`?`text-danger`:`text-primary`])},[u(`span`,{class:d([`w-2 h-2 rounded-full mr-1.5`,t.status===`success`?`bg-success shadow-[0_0_8px_#10b981]`:t.status===`failed`?`bg-danger`:`bg-primary`])},null,2),v(` `+m(t.status===`success`?`正常`:t.status===`failed`?`异常`:`空闲`),1)],2)])])],8,Ye))),128)),Er.value.length===0?(e(),f(`div`,ut,` 当前分类下没有项目 `)):p(``,!0)])):(e(),f(`div`,dt,[u(`div`,ft,[u(`table`,pt,[r[55]||=u(`thead`,{class:`text-xs text-textMuted bg-base/40`},[u(`tr`,null,[u(`th`,{class:`text-left font-medium px-4 py-3`},`项目名`),u(`th`,{class:`text-left font-medium px-4 py-3`},`部署目录`),u(`th`,{class:`text-left font-medium px-4 py-3 w-28`},`分类`),u(`th`,{class:`text-left font-medium px-4 py-3 w-24`},`环境`),u(`th`,{class:`text-left font-medium px-4 py-3 w-36`},`上次部署`),u(`th`,{class:`text-left font-medium px-4 py-3 w-20`},`状态`),u(`th`,{class:`text-right font-medium px-4 py-3 w-12`})])],-1),u(`tbody`,null,[(e(!0),f(c,null,i(Er.value,t=>(e(),f(`tr`,{key:t.id,class:`border-t border-border hover:bg-white/5 cursor-pointer`,onClick:e=>Lr(t.id)},[u(`td`,ht,[u(`div`,gt,[y(g(pe),{class:`w-4 h-4 text-textMuted`}),u(`div`,null,[u(`div`,_t,m(t.name),1),u(`div`,vt,m(t.id),1)])])]),u(`td`,yt,m(t.destPath||`—`),1),u(`td`,bt,[u(`div`,xt,[u(`span`,{class:d([`inline-flex items-center px-2 py-0.5 rounded text-[10px] border`,Ar(Tr.value.get(t.categoryId||``)?.color)])},[y(g(x),{class:`w-3 h-3 mr-1`}),v(` `+m(Nr(t.categoryId)),1)],2),y(ge,{"model-value":t.tagIds||[],size:`sm`,"on-persist":e=>Ai(t.id,e),"aria-label":`编辑「${t.name}」的标签`},null,8,[`model-value`,`on-persist`,`aria-label`])])]),u(`td`,St,[t.env?(e(),f(`span`,{key:0,class:d([`inline-flex items-center px-2 py-0.5 rounded text-[10px] border font-mono`,Mr(t.env)])},m(t.env),3)):(e(),f(`span`,Ct,`—`))]),u(`td`,{class:`px-4 py-3 text-textMuted text-xs`,title:t.lastDeployAt?new Date(t.lastDeployAt).toLocaleString():`从未部署`},m(Pr(t.lastDeployAt)),9,wt),u(`td`,Tt,[u(`span`,{class:d([`inline-flex items-center text-xs`,t.status===`success`?`text-success`:t.status===`failed`?`text-danger`:`text-primary`])},[u(`span`,{class:d([`w-2 h-2 rounded-full mr-1.5`,t.status===`success`?`bg-success`:t.status===`failed`?`bg-danger`:`bg-primary`])},null,2),v(` `+m(t.status===`success`?`正常`:t.status===`failed`?`异常`:`空闲`),1)],2)]),u(`td`,Et,[u(`button`,{class:`p-1 dark:hover:bg-white/10 hover:bg-black/10 rounded-md text-textMuted hover:text-textMain`,onClick:E(e=>Hr(t.id,e),[`stop`])},[y(g(Te),{class:`w-4 h-4`})],8,Dt)])],8,mt))),128)),Er.value.length===0?(e(),f(`tr`,Ot,[...r[54]||=[u(`td`,{colspan:`7`,class:`px-4 py-12 text-center text-textMuted text-sm`},`当前分类下没有项目`,-1)]])):p(``,!0)])])])])),(e(),h(te,{to:`body`},[y(ve,{name:`fade`},{default:t(()=>[P.value?(e(),f(`div`,{key:0,class:`bg-panel border border-border rounded-lg shadow-xl py-1`,style:re({...Vr.value,zIndex:60}),onClick:r[15]||=E(()=>{},[`stop`])},[u(`button`,{class:`flex items-center w-full px-3 py-2 text-sm text-textMain hover:bg-white/5 transition-colors`,onClick:r[7]||=e=>{(()=>{let e=g(_).projects.find(e=>e.id===P.value);e&&Wr(e.id,e.name)})()}},[y(g(se),{class:`w-3.5 h-3.5 mr-2 text-textMuted`}),r[56]||=v(` 重命名 `,-1)]),u(`button`,{class:`flex items-center w-full px-3 py-2 text-sm text-textMain hover:bg-white/5 transition-colors`,onClick:r[8]||=E(e=>{(()=>{let e=P.value;F(),e&&Br(e)})()},[`stop`])},[y(g(ue),{class:`w-3.5 h-3.5 mr-2 text-textMuted`}),r[57]||=v(` 查看文件 `,-1)]),u(`button`,{class:`flex items-center w-full px-3 py-2 text-sm text-textMain hover:bg-white/5 transition-colors`,onClick:r[9]||=e=>{(()=>{let e=P.value;F(),e&&Rr(e)})()}},[y(g(fe),{class:`w-3.5 h-3.5 mr-2 text-textMuted`}),r[58]||=v(` 部署日志 `,-1)]),u(`button`,{class:`flex items-center w-full px-3 py-2 text-sm text-textMain hover:bg-white/5 transition-colors`,onClick:r[10]||=e=>{(()=>{let e=P.value;F(),e&&zr(e)})()}},[y(g(ae),{class:`w-3.5 h-3.5 mr-2 text-textMuted`}),r[59]||=v(` 运行日志 `,-1)]),r[63]||=u(`div`,{class:`border-t border-border my-1`},null,-1),u(`div`,kt,[u(`button`,{class:`flex items-center justify-between w-full px-3 py-2 text-sm text-textMain hover:bg-white/5 transition-colors`,onClick:r[11]||=e=>mi(e)},[u(`span`,At,[y(g(De),{class:`w-3.5 h-3.5 mr-2 text-textMuted`}),r[60]||=v(` 移动到分类 `,-1)]),y(g(ce),{class:`w-3.5 h-3.5 text-textMuted`})]),fi.value?(e(),f(`div`,{key:0,class:`absolute top-0 right-full mr-1 bg-panel border border-border rounded-lg shadow-xl py-1 min-w-[160px] max-h-64 overflow-auto`,style:{"z-index":`61`},onClick:r[13]||=E(()=>{},[`stop`])},[u(`button`,{class:`flex items-center w-full px-3 py-2 text-sm text-textMain hover:bg-white/5 transition-colors`,disabled:pi.value,onClick:r[12]||=e=>P.value&&hi(P.value,null)},[...r[61]||=[u(`span`,{class:`inline-flex items-center px-2 py-0.5 rounded text-[10px] border bg-base text-textMuted border-border`},`默认`,-1)]],8,jt),(e(!0),f(c,null,i(g(_).categories,t=>(e(),f(`button`,{key:t.id,class:`flex items-center w-full px-3 py-2 text-sm text-textMain hover:bg-white/5 transition-colors`,disabled:pi.value,onClick:e=>P.value&&hi(P.value,t.id)},[u(`span`,{class:d([`inline-flex items-center px-2 py-0.5 rounded text-[10px] border`,Ar(t.color)])},[y(g(x),{class:`w-3 h-3 mr-1`}),v(m(t.name),1)],2)],8,Mt))),128)),g(_).categories.length===0?(e(),f(`div`,Nt,` 还没有分类,请先在「管理分类」中创建 `)):p(``,!0)])):p(``,!0)]),r[64]||=u(`div`,{class:`border-t border-border my-1`},null,-1),u(`button`,{class:`flex items-center w-full px-3 py-2 text-sm text-danger hover:bg-danger/10 transition-colors`,onClick:r[14]||=e=>{(()=>{let e=g(_).projects.find(e=>e.id===P.value);e&&qr(e.id,e.name)})()}},[y(g(_e),{class:`w-3.5 h-3.5 mr-2`}),r[62]||=v(` 删除项目 `,-1)])],4)):p(``,!0)]),_:1})])),Fr.value?(e(),f(`div`,Pt,[u(`div`,Ft,[r[73]||=u(`h2`,{class:`text-xl font-bold text-textMain mb-6`},`新建部署项目`,-1),u(`div`,It,[u(`div`,null,[r[65]||=u(`label`,{class:`block text-sm font-medium text-textMuted mb-1.5`},`项目名称`,-1),s(u(`input`,{"onUpdate:modelValue":r[16]||=e=>N.value.name=e,type:`text`,class:`w-full bg-base border border-border rounded-md px-3 py-2 text-textMain focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all text-sm`,placeholder:`e.g. Kite Web Frontend`},null,512),[[C,N.value.name]])]),u(`div`,null,[r[66]||=u(`label`,{class:`block text-sm font-medium text-textMuted mb-1.5`},`部署目录绝对路径 (Destination Path)`,-1),s(u(`input`,{"onUpdate:modelValue":r[17]||=e=>N.value.destPath=e,type:`text`,class:`w-full bg-base border border-border rounded-md px-3 py-2 text-textMain font-mono focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all text-sm`,placeholder:`e.g. /var/www/my-project`},null,512),[[C,N.value.destPath]])]),u(`div`,null,[r[67]||=u(`label`,{class:`block text-sm font-medium text-textMuted mb-1.5`},`部署环境标识 (可选)`,-1),s(u(`input`,{"onUpdate:modelValue":r[18]||=e=>N.value.env=e,type:`text`,class:`w-full bg-base border border-border rounded-md px-3 py-2 text-textMain font-mono focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all text-sm`,placeholder:`e.g. test, staging, prod`},null,512),[[C,N.value.env]]),r[68]||=u(`p`,{class:`text-xs text-textMuted mt-1.5`},[v(` 用于区分同一项目的不同部署环境。设置后,CLI 会生成 `),u(`code`,{class:`font-mono text-textMain`},"kite.config.{`{env}`}.json"),v(` 配置文件, `),u(`code`,{class:`font-mono text-textMain`},"kite push --env {`{name}`}"),v(` 可精准推送到对应环境。 `),u(`span`,{class:`text-primary/80`},`常见场景:同一项目部署到测试/预发/生产等不同机器。`)],-1)]),u(`div`,null,[r[70]||=u(`label`,{class:`block text-sm font-medium text-textMuted mb-1.5`},`分类 (可选)`,-1),s(u(`select`,{"onUpdate:modelValue":r[19]||=e=>N.value.categoryId=e,class:`w-full bg-base border border-border rounded-md px-3 py-2 text-textMain focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all text-sm`},[r[69]||=u(`option`,{value:``},`默认`,-1),(e(!0),f(c,null,i(g(_).categories,t=>(e(),f(`option`,{key:t.id,value:t.id},m(t.name),9,Lt))),128))],512),[[ye,N.value.categoryId]])]),u(`div`,null,[r[71]||=u(`label`,{class:`block text-sm font-medium text-textMuted mb-1.5`},`标签 (可选,可多选)`,-1),g(_).tags.length===0?(e(),f(`div`,Rt,` 还没有标签,可前往「管理标签」创建。 `)):(e(),f(`div`,zt,[(e(!0),f(c,null,i(g(_).tags,t=>(e(),f(`button`,{key:t.id,type:`button`,onClick:e=>ji(N.value,t.id),class:d([`inline-flex items-center px-2 py-1 rounded text-[11px] border transition-colors`,N.value.tagIds.includes(t.id)?`${g(S)(t.color)} ring-1 ring-primary/40`:`bg-base text-textMuted border-border hover:text-textMain hover:border-textMuted/40`])},[y(g(x),{class:`w-3 h-3 mr-1`}),v(` `+m(t.name),1)],10,Bt))),128))]))]),u(`div`,null,[r[72]||=u(`label`,{class:`block text-sm font-medium text-textMuted mb-1.5`},`描述 (可选)`,-1),s(u(`textarea`,{"onUpdate:modelValue":r[20]||=e=>N.value.description=e,class:`w-full bg-base border border-border rounded-md px-3 py-2 text-textMain focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all text-sm h-24 resize-none`,placeholder:`简要描述项目的用途...`},null,512),[[C,N.value.description]])])]),u(`div`,Vt,[u(`button`,{onClick:r[21]||=e=>Fr.value=!1,class:`px-4 py-2 text-sm font-medium text-textMuted hover:text-textMain dark:hover:bg-white/5 hover:bg-black/5 rounded-md transition-colors`},` 取消 `),u(`button`,{onClick:Ir,disabled:!N.value.name||!N.value.destPath,class:`px-4 py-2 text-sm font-medium bg-primary text-white rounded-md hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors`},` 确认创建 `,8,Ht)])])])):p(``,!0),y(oe,{open:Xr.value,"onUpdate:open":r[22]||=e=>Xr.value=e,mode:`multi`,title:`选择部署目录`,onConfirm:ai},null,8,[`open`]),Zr.value?(e(),f(`div`,{key:5,class:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,onClick:E(di,[`self`])},[u(`div`,Ut,[u(`div`,Wt,[u(`div`,null,[r[74]||=u(`h2`,{class:`text-xl font-bold text-textMain`},`批量创建部署项目`,-1),u(`p`,Gt,`将创建 `+m(W.value.length)+` 个项目,默认使用目录名作为项目名,可逐行修改`,1)]),u(`button`,{onClick:di,disabled:U.value,class:`text-textMuted hover:text-textMain p-1 disabled:opacity-40`},[y(g(Se),{class:`w-5 h-5`})],8,Kt)]),u(`div`,qt,[y(g(be),{class:`w-4 h-4 text-yellow-600 dark:text-yellow-400 flex-shrink-0 mt-0.5`}),r[75]||=u(`p`,{class:`text-xs text-yellow-800 dark:text-yellow-200/90`},` 请确认所选目录用于部署。每次部署会在该目录下解压新构建产物,请勿选择关键系统目录或包含重要个人文件的目录。 `,-1)]),u(`div`,Jt,[u(`table`,Yt,[r[78]||=u(`thead`,{class:`text-xs text-textMuted sticky top-0 bg-panel`},[u(`tr`,{class:`border-b border-border`},[u(`th`,{class:`text-left font-medium px-3 py-2 w-[16%]`},`项目名`),u(`th`,{class:`text-left font-medium px-3 py-2 w-[30%]`},`部署目录`),u(`th`,{class:`text-left font-medium px-3 py-2 w-[10%]`},`环境标识`),u(`th`,{class:`text-left font-medium px-3 py-2 w-[12%]`},`分类`),u(`th`,{class:`text-left font-medium px-3 py-2 w-[16%]`},`标签`),u(`th`,{class:`text-left font-medium px-3 py-2 w-[16%]`},`描述`)])],-1),u(`tbody`,null,[(e(!0),f(c,null,i(W.value,t=>(e(),f(`tr`,{key:t.id,class:d([`border-b border-border/60 align-top`,t.status===`success`?`opacity-60`:``])},[u(`td`,Xt,[s(u(`input`,{"onUpdate:modelValue":e=>t.name=e,type:`text`,disabled:t.status===`success`||U.value,class:d([`w-full bg-base border rounded px-2 py-1.5 text-textMain text-sm focus:outline-none focus:ring-1 focus:ring-primary/50 disabled:opacity-60`,G.value.get(t.id)?.name?`border-danger`:`border-border focus:border-primary`])},null,10,Zt),[[C,t.name]]),G.value.get(t.id)?.name?(e(),f(`p`,Qt,m(G.value.get(t.id)?.name),1)):p(``,!0)]),u(`td`,$t,[s(u(`textarea`,{"onUpdate:modelValue":e=>t.destPath=e,rows:`2`,spellcheck:`false`,disabled:t.status===`success`||U.value,class:d([`w-full bg-base border rounded px-2 py-1.5 text-textMain font-mono text-xs leading-5 focus:outline-none focus:ring-1 focus:ring-primary/50 disabled:opacity-60 resize-y whitespace-pre-wrap break-all`,G.value.get(t.id)?.dest?`border-danger`:`border-border focus:border-primary`]),title:t.destPath},null,10,en),[[C,t.destPath]]),G.value.get(t.id)?.dest?(e(),f(`p`,tn,m(G.value.get(t.id)?.dest),1)):p(``,!0),t.status===`failed`&&t.errorMsg?(e(),f(`p`,nn,m(t.errorMsg),1)):p(``,!0)]),u(`td`,rn,[s(u(`input`,{"onUpdate:modelValue":e=>t.env=e,type:`text`,placeholder:`test/prod`,disabled:t.status===`success`||U.value,class:`w-full bg-base border border-border rounded px-2 py-1.5 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 disabled:opacity-60`},null,8,an),[[C,t.env]])]),u(`td`,on,[s(u(`select`,{"onUpdate:modelValue":e=>t.categoryId=e,disabled:t.status===`success`||U.value,class:`w-full bg-base border border-border rounded px-2 py-1.5 text-textMain text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 disabled:opacity-60`},[r[76]||=u(`option`,{value:``},`默认`,-1),(e(!0),f(c,null,i(g(_).categories,t=>(e(),f(`option`,{key:t.id,value:t.id},m(t.name),9,cn))),128))],8,sn),[[ye,t.categoryId]])]),u(`td`,ln,[g(_).tags.length===0?(e(),f(`div`,un,`无`)):(e(),f(`div`,dn,[(e(!0),f(c,null,i(g(_).tags,n=>(e(),f(`button`,{key:n.id,type:`button`,disabled:t.status===`success`||U.value,onClick:e=>ji(t,n.id),class:d([`inline-flex items-center px-1.5 py-0.5 rounded text-[10px] border transition-colors disabled:opacity-60`,t.tagIds.includes(n.id)?`${g(S)(n.color)} ring-1 ring-primary/40`:`bg-base text-textMuted border-border hover:text-textMain hover:border-textMuted/40`])},m(n.name),11,fn))),128))]))]),u(`td`,pn,[u(`div`,mn,[s(u(`input`,{"onUpdate:modelValue":e=>t.description=e,type:`text`,placeholder:`可选`,disabled:t.status===`success`||U.value,class:`flex-1 min-w-0 bg-base border border-border rounded px-2 py-1.5 text-textMain text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 disabled:opacity-60`},null,8,hn),[[C,t.description]]),t.status===`success`?p(``,!0):(e(),f(`button`,{key:0,onClick:e=>oi(t.id),disabled:U.value,class:`shrink-0 mt-1.5 text-textMuted hover:text-danger disabled:opacity-40`,title:`移除该行`},[y(g(_e),{class:`w-3.5 h-3.5`})],8,gn))])])],2))),128)),W.value.length===0?(e(),f(`tr`,_n,[...r[77]||=[u(`td`,{colspan:`6`,class:`px-3 py-8 text-center text-textMuted text-sm`},`没有待创建的项目`,-1)]])):p(``,!0)])])]),u(`div`,vn,[u(`div`,yn,[u(`button`,{onClick:ii,disabled:U.value,class:`flex items-center px-3 py-1.5 text-xs border border-border rounded-md text-textMuted hover:text-textMain disabled:opacity-40`},[y(g(Ee),{class:`w-3.5 h-3.5 mr-1.5`}),r[79]||=v(` 继续添加 `,-1)],8,bn),u(`div`,xn,` 共 `+m(K.value.total)+` · 待提交 `+m(K.value.pending)+` · 成功 `+m(K.value.success)+` · 失败 `+m(K.value.failed),1)]),u(`div`,Sn,[u(`button`,{onClick:di,disabled:U.value,class:`px-4 py-2 text-sm font-medium text-textMuted hover:text-textMain dark:hover:bg-white/5 hover:bg-black/5 rounded-md transition-colors disabled:opacity-50`},m(K.value.success>0?`完成`:`取消`),9,Cn),u(`button`,{onClick:ui,disabled:!li.value,class:`px-4 py-2 text-sm font-medium bg-primary text-white rounded-md hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center`},[U.value?(e(),h(g(b),{key:0,class:`w-4 h-4 mr-2 animate-spin`})):p(``,!0),v(` `+m(U.value?`提交中…`:`提交(${K.value.pending})`),1)],8,wn)])])])])):p(``,!0),(e(),h(te,{to:`body`},[P.value?(e(),f(`div`,{key:0,class:`fixed inset-0`,style:{"z-index":`55`},onClick:F})):p(``,!0)])),I.value?(e(),f(`div`,{key:6,class:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,onClick:r[25]||=E(e=>I.value=!1,[`self`])},[u(`div`,Tn,[r[82]||=u(`h2`,{class:`text-lg font-semibold text-textMain mb-4`},`重命名项目`,-1),u(`div`,null,[r[80]||=u(`label`,{class:`block text-sm font-medium text-textMuted mb-1.5`},`项目名称`,-1),s(u(`input`,{"onUpdate:modelValue":r[23]||=e=>R.value=e,type:`text`,disabled:z.value,class:`w-full bg-base border border-border rounded-md px-3 py-2 text-textMain focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all text-sm disabled:opacity-60`,placeholder:`输入新的项目名称`,onKeydown:T(E(Gr,[`prevent`]),[`enter`])},null,40,En),[[C,R.value]])]),u(`div`,Dn,[u(`button`,{onClick:r[24]||=e=>I.value=!1,disabled:z.value,class:`px-4 py-2 text-sm font-medium text-textMuted hover:text-textMain dark:hover:bg-white/5 hover:bg-black/5 rounded-md transition-colors disabled:opacity-50`},`取消`,8,On),u(`button`,{onClick:Gr,disabled:z.value||!R.value.trim()||R.value.trim()===L.value?.name,class:`px-4 py-2 text-sm font-medium bg-primary text-white rounded-md hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center`},[z.value?(e(),h(g(b),{key:0,class:`w-4 h-4 mr-2 animate-spin`})):p(``,!0),r[81]||=v(` 确认 `,-1)],8,kn)])])])):p(``,!0),B.value?(e(),f(`div`,{key:7,class:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,onClick:r[28]||=E(e=>!H.value&&(B.value=!1),[`self`])},[u(`div`,An,[u(`div`,jn,[u(`div`,Mn,[y(g(be),{class:`w-5 h-5 text-danger`})]),u(`div`,null,[r[85]||=u(`h2`,{class:`text-lg font-semibold text-textMain`},`确认删除项目`,-1),u(`p`,Nn,[r[83]||=v(` 即将删除项目 `,-1),u(`span`,Pn,m(V.value?.name),1),r[84]||=v(`, 此操作不可恢复。 `,-1)])])]),u(`div`,Fn,[u(`label`,In,[r[86]||=v(` 请输入项目名称 `,-1),u(`span`,Ln,m(V.value?.name),1),r[87]||=v(` 以确认删除 `,-1)]),s(u(`input`,{"onUpdate:modelValue":r[26]||=e=>Kr.value=e,type:`text`,disabled:H.value,placeholder:V.value?.name,class:`w-full bg-base border border-border rounded-md px-3 py-2 text-textMain font-mono focus:outline-none focus:border-danger focus:ring-1 focus:ring-danger/50 transition-all text-sm disabled:opacity-60`,onKeydown:T(E(Yr,[`prevent`]),[`enter`])},null,40,Rn),[[C,Kr.value]])]),u(`div`,zn,[u(`button`,{onClick:r[27]||=e=>B.value=!1,disabled:H.value,class:`px-4 py-2 text-sm font-medium text-textMuted hover:text-textMain dark:hover:bg-white/5 hover:bg-black/5 rounded-md transition-colors disabled:opacity-50`},`取消`,8,Bn),u(`button`,{onClick:Yr,disabled:!Jr.value,class:`px-4 py-2 text-sm font-medium bg-danger text-white rounded-md hover:bg-danger/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center`},[H.value?(e(),h(g(b),{key:0,class:`w-4 h-4 mr-2 animate-spin`})):(e(),h(g(_e),{key:1,class:`w-4 h-4 mr-2`})),v(` `+m(H.value?`正在删除...`:`永久删除`),1)],8,Vn)])])])):p(``,!0),gi.value?(e(),f(`div`,{key:8,class:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,onClick:r[33]||=E(e=>gi.value=!1,[`self`])},[u(`div`,Hn,[u(`div`,Un,[r[88]||=u(`div`,null,[u(`h2`,{class:`text-xl font-bold text-textMain`},`管理分类`),u(`p`,{class:`text-xs text-textMuted mt-1`},`创建、编辑、删除分类。删除分类后,相关项目将回落到「默认」。`)],-1),u(`button`,{onClick:r[29]||=e=>gi.value=!1,class:`text-textMuted hover:text-textMain p-1`},[y(g(Se),{class:`w-5 h-5`})])]),u(`div`,Wn,[r[90]||=u(`label`,{class:`block text-sm font-medium text-textMuted mb-2`},`新建分类`,-1),u(`div`,Gn,[s(u(`input`,{"onUpdate:modelValue":r[30]||=e=>q.value=e,type:`text`,placeholder:`如:前端 / 后端 / 测试环境`,disabled:_i.value,class:`flex-1 bg-base border border-border rounded-md px-3 py-2 text-textMain focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all text-sm disabled:opacity-60`,onKeydown:T(E(Ci,[`prevent`]),[`enter`])},null,40,Kn),[[C,q.value]]),u(`button`,{onClick:Ci,disabled:_i.value||!q.value.trim(),class:`px-4 py-2 text-sm font-medium bg-primary text-white rounded-md hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center`},[_i.value?(e(),h(g(b),{key:0,class:`w-4 h-4 mr-2 animate-spin`})):(e(),h(g(de),{key:1,class:`w-4 h-4 mr-1`})),r[89]||=v(` 新建 `,-1)],8,qn)]),r[91]||=u(`p`,{class:`text-xs text-textMuted mt-2`},`颜色将自动分配,不同分类之间不重复。`,-1)]),u(`div`,Jn,[g(_).categories.length===0?(e(),f(`div`,Yn,` 还没有分类,新建一个吧 `)):(e(),f(`ul`,Xn,[(e(!0),f(c,null,i(g(_).categories,t=>(e(),f(`li`,{key:t.id,class:`py-3 flex items-center justify-between gap-3`},[J.value===t.id?(e(),f(c,{key:0},[s(u(`input`,{"onUpdate:modelValue":r[31]||=e=>Y.value=e,type:`text`,disabled:vi.value,class:`flex-1 bg-base border border-border rounded-md px-3 py-2 text-textMain focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all text-sm disabled:opacity-60`,onKeydown:T(E(Ei,[`prevent`]),[`enter`])},null,40,Zn),[[C,Y.value]]),u(`button`,{onClick:Ei,disabled:vi.value||!Y.value.trim(),class:`px-3 py-1.5 text-xs font-medium bg-primary text-white rounded-md hover:bg-primary/90 disabled:opacity-50 transition-colors`},`保存`,8,Qn),u(`button`,{onClick:Ti,disabled:vi.value,class:`px-3 py-1.5 text-xs font-medium text-textMuted hover:text-textMain transition-colors`},`取消`,8,$n)],64)):(e(),f(c,{key:1},[u(`span`,{class:d([`inline-flex items-center px-2 py-1 rounded text-xs border`,Ar(t.color)])},[y(g(x),{class:`w-3 h-3 mr-1.5`}),v(` `+m(t.name),1)],2),u(`span`,er,m(Dr.value[t.id]||0)+` 个项目`,1),u(`button`,{onClick:e=>wi(t),class:`px-3 py-1.5 text-xs font-medium text-textMuted hover:text-textMain transition-colors flex items-center`},[y(g(se),{class:`w-3 h-3 mr-1`}),r[92]||=v(` 编辑 `,-1)],8,tr),u(`button`,{onClick:e=>Di(t),disabled:yi.value===t.id,class:`px-3 py-1.5 text-xs font-medium text-danger hover:bg-danger/10 rounded-md transition-colors flex items-center disabled:opacity-50`},[yi.value===t.id?(e(),h(g(b),{key:0,class:`w-3 h-3 mr-1 animate-spin`})):(e(),h(g(_e),{key:1,class:`w-3 h-3 mr-1`})),r[93]||=v(` 删除 `,-1)],8,nr)],64))]))),128))]))]),u(`div`,rr,[u(`button`,{onClick:r[32]||=e=>gi.value=!1,class:`px-4 py-2 text-sm font-medium text-textMuted hover:text-textMain dark:hover:bg-white/5 hover:bg-black/5 rounded-md transition-colors`},`完成`)])])])):p(``,!0),Mi.value?(e(),f(`div`,{key:9,class:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,onClick:r[38]||=E(e=>Mi.value=!1,[`self`])},[u(`div`,ir,[u(`div`,ar,[r[94]||=u(`div`,null,[u(`h2`,{class:`text-xl font-bold text-textMain`},`管理标签`),u(`p`,{class:`text-xs text-textMuted mt-1`},`创建、编辑、删除项目标签。删除标签会解除其与项目的关联。`)],-1),u(`button`,{onClick:r[34]||=e=>Mi.value=!1,class:`text-textMuted hover:text-textMain p-1`},[y(g(Se),{class:`w-5 h-5`})])]),u(`div`,or,[r[96]||=u(`label`,{class:`block text-sm font-medium text-textMuted mb-2`},`新建标签`,-1),u(`div`,sr,[s(u(`input`,{"onUpdate:modelValue":r[35]||=e=>X.value=e,type:`text`,placeholder:`如:前端 / Node / PM2`,disabled:Ni.value,class:`flex-1 bg-base border border-border rounded-md px-3 py-2 text-textMain focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all text-sm disabled:opacity-60`,onKeydown:T(E(Ii,[`prevent`]),[`enter`])},null,40,cr),[[C,X.value]]),u(`button`,{onClick:Ii,disabled:Ni.value||!X.value.trim(),class:`px-4 py-2 text-sm font-medium bg-primary text-white rounded-md hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center`},[Ni.value?(e(),h(g(b),{key:0,class:`w-4 h-4 mr-2 animate-spin`})):(e(),h(g(de),{key:1,class:`w-4 h-4 mr-1`})),r[95]||=v(` 新建 `,-1)],8,lr)]),r[97]||=u(`p`,{class:`text-xs text-textMuted mt-2`},`颜色将自动分配,可在下方点击色块切换。`,-1)]),u(`div`,ur,[g(_).tags.length===0?(e(),f(`div`,dr,` 还没有标签,新建一个吧 `)):(e(),f(`ul`,fr,[(e(!0),f(c,null,i(g(_).tags,t=>(e(),f(`li`,{key:t.id,class:`py-3 flex items-center justify-between gap-3 flex-wrap`},[Z.value===t.id?(e(),f(c,{key:0},[s(u(`input`,{"onUpdate:modelValue":r[36]||=e=>Q.value=e,type:`text`,disabled:Pi.value,class:`flex-1 bg-base border border-border rounded-md px-3 py-2 text-textMain focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all text-sm disabled:opacity-60`,onKeydown:T(E(zi,[`prevent`]),[`enter`])},null,40,pr),[[C,Q.value]]),u(`button`,{onClick:zi,disabled:Pi.value||!Q.value.trim(),class:`px-3 py-1.5 text-xs font-medium bg-primary text-white rounded-md hover:bg-primary/90 disabled:opacity-50 transition-colors`},`保存`,8,mr),u(`button`,{onClick:Ri,disabled:Pi.value,class:`px-3 py-1.5 text-xs font-medium text-textMuted hover:text-textMain transition-colors`},`取消`,8,hr)],64)):(e(),f(c,{key:1},[u(`span`,{class:d([`inline-flex items-center px-2 py-1 rounded text-xs border`,g(S)(t.color)])},[y(g(x),{class:`w-3 h-3 mr-1.5`}),v(` `+m(t.name),1)],2),u(`div`,gr,[(e(!0),f(c,null,i(g(he),n=>(e(),f(`button`,{key:n,type:`button`,title:`切换为 ${n}`,onClick:e=>Bi(t,n),class:d([`w-4 h-4 rounded-full border`,[g(S)(n),t.color===n?`ring-2 ring-primary`:``]])},null,10,_r))),128))]),u(`span`,vr,m(t.projectCount||0)+` 个项目`,1),u(`button`,{onClick:e=>Li(t),class:`px-3 py-1.5 text-xs font-medium text-textMuted hover:text-textMain transition-colors flex items-center`},[y(g(se),{class:`w-3 h-3 mr-1`}),r[98]||=v(` 编辑 `,-1)],8,yr),u(`button`,{onClick:e=>Vi(t),disabled:$.value===t.id,class:`px-3 py-1.5 text-xs font-medium text-danger hover:bg-danger/10 rounded-md transition-colors flex items-center disabled:opacity-50`},[$.value===t.id?(e(),h(g(b),{key:0,class:`w-3 h-3 mr-1 animate-spin`})):(e(),h(g(_e),{key:1,class:`w-3 h-3 mr-1`})),r[99]||=v(` 删除 `,-1)],8,br)],64))]))),128))]))]),u(`div`,xr,[u(`button`,{onClick:r[37]||=e=>Mi.value=!1,class:`px-4 py-2 text-sm font-medium text-textMuted hover:text-textMain dark:hover:bg-white/5 hover:bg-black/5 rounded-md transition-colors`},`完成`)])])])):p(``,!0)]))}}),[[`__scopeId`,`data-v-21550dfd`]]);export{D as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.fade-enter-active[data-v-21550dfd],.fade-leave-active[data-v-21550dfd]{transition:opacity .12s}.fade-enter-from[data-v-21550dfd],.fade-leave-to[data-v-21550dfd]{opacity:0}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{A as e,E as t,M as n,T as r,U as i,V as ee,b as a,c as o,d as s,f as c,ft as l,h as u,l as te,m as d,mt as f,n as p,p as m,pt as h,q as g,t as _,v,y,z as b}from"./createLucideIcon-BmsTm7z-.js";import{n as x}from"./pencil-BTFuj0gA.js";import{t as S}from"./plus-CcefsCv_.js";import{g as ne,n as re,r as C,y as w}from"./index-BZU6i5nw.js";var T=_(`tag`,[[`path`,{d:`M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z`,key:`vktsd0`}],[`circle`,{cx:`7.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`kqv944`}]]),E=[`blue`,`green`,`yellow`,`purple`,`pink`,`cyan`,`gray`];new Set(E);var D={blue:`bg-blue-500/15 text-blue-500 border-blue-500/30`,green:`bg-green-500/15 text-green-500 border-green-500/30`,yellow:`bg-yellow-500/15 text-yellow-500 border-yellow-500/30`,purple:`bg-purple-500/15 text-purple-500 border-purple-500/30`,pink:`bg-pink-500/15 text-pink-500 border-pink-500/30`,cyan:`bg-cyan-500/15 text-cyan-500 border-cyan-500/30`,gray:`bg-gray-500/15 text-gray-400 border-gray-500/30`};function O(e){return e&&D[e]?D[e]:`bg-base text-textMuted border-border`}function k(e){let t=new Set;for(let n of e)n.color&&t.add(n.color);for(let e of E)if(!t.has(e))return e;return E[e.length%E.length]}var A=[`title`,`onClick`],j=[`aria-label`,`title`],M={class:`flex items-center justify-between mb-2`},N={class:`flex items-center flex-wrap gap-1.5 max-h-40 overflow-auto mb-2 pr-1`},P=[`onClick`],F={key:1,class:`text-textMuted`},I=[`disabled`],L=a({__name:`ProjectTagsEditor`,props:{modelValue:{},size:{default:`sm`},readOnlySave:{type:Boolean,default:!1},onPersist:{type:Function,default:void 0},ariaLabel:{default:`编辑标签`}},emits:[`update:modelValue`],setup(a,{emit:_}){let E=a,D=_,k=p(),L=re(),R=s(()=>{let e=new Map;for(let t of k.tags)e.set(t.id,t);return e}),z=s(()=>Array.isArray(E.modelValue)?E.modelValue:[]),B=i(!1),V=i(null),H=i(null),U=i(``),W=i(!1),G=i({});function K(){if(!H.value)return;let e=H.value.getBoundingClientRect(),t=e.left,n=window.innerWidth-280-8;t>n&&(t=Math.max(8,n));let r=e.bottom+4;r+320>window.innerHeight&&(r=Math.max(8,e.top-4-320)),G.value={position:`fixed`,top:`${r}px`,left:`${t}px`,width:`280px`,"z-index":`60`}}async function q(e){if(e.stopPropagation(),B.value){J();return}k.tags.length===0&&await k.fetchTags(),B.value=!0,await r(),K()}function J(){B.value=!1,U.value=``}function Y(e){if(!B.value)return;let t=e.target;V.value?.contains(t)||H.value?.contains(t)||J()}function X(){B.value&&K()}function Z(e){B.value&&e.key===`Escape`&&J()}document.addEventListener(`click`,Y,!0),window.addEventListener(`resize`,X),window.addEventListener(`scroll`,X,!0),document.addEventListener(`keydown`,Z),t(()=>{document.removeEventListener(`click`,Y,!0),window.removeEventListener(`resize`,X),window.removeEventListener(`scroll`,X,!0),document.removeEventListener(`keydown`,Z)});async function Q(e){if(D(`update:modelValue`,e),!E.readOnlySave&&E.onPersist)try{await E.onPersist(e)}catch(e){L.error(`保存标签失败`,e?.message||`请稍后重试`)}}async function ie(e){let t=[...z.value],n=t.indexOf(e);n===-1?t.push(e):t.splice(n,1),await Q(t)}async function ae(e,t){t?.stopPropagation(),await Q(z.value.filter(t=>t!==e))}async function oe(){let e=U.value.trim();if(!(!e||W.value)){W.value=!0;try{let t=k.tags.find(t=>t.name===e);if(t){z.value.includes(t.id)||await Q([...z.value,t.id]),U.value=``;return}let n=await k.createTag({name:e});if(n.ok&&n.tag){await Q([...z.value,n.tag.id]),U.value=``;return}if(n.conflictTag){await k.fetchTags();let e=k.tags.find(e=>e.name===n.conflictTag);if(e){z.value.includes(e.id)||await Q([...z.value,e.id]),U.value=``;return}}L.error(`创建标签失败`,n.error||`请稍后重试`)}finally{W.value=!1}}}let $=s(()=>E.size===`md`?`px-2 py-0.5 text-xs`:`px-2 py-0.5 text-[10px]`);return b(()=>E.modelValue,()=>{B.value&&r(K)}),(t,r)=>(e(),u(`div`,{class:`inline-flex items-center flex-wrap gap-1.5 align-middle`,onClick:r[2]||=w(()=>{},[`stop`])},[(e(!0),u(o,null,n(z.value,t=>(e(),u(o,{key:t},[R.value.get(t)?(e(),u(`span`,{key:0,class:l([`group/tag inline-flex items-center rounded border transition-colors`,[$.value,g(O)(R.value.get(t)?.color)]])},[y(g(T),{class:`w-3 h-3 mr-1`}),v(` `+f(R.value.get(t)?.name)+` `,1),c(`button`,{type:`button`,class:`ml-1 -mr-0.5 opacity-60 hover:opacity-100 hover:text-danger transition-opacity`,title:`移除标签 ${R.value.get(t)?.name}`,onClick:e=>ae(t,e)},[y(g(C),{class:`w-3 h-3`})],8,A)],2)):d(``,!0)],64))),128)),c(`button`,{ref_key:`triggerEl`,ref:H,type:`button`,class:l([`inline-flex items-center rounded border border-dashed border-border text-textMuted hover:text-primary hover:border-primary/50 transition-colors`,$.value]),"aria-label":a.ariaLabel,title:a.ariaLabel,onClick:q},[y(g(S),{class:`w-3 h-3 mr-0.5`}),r[3]||=c(`span`,null,`标签`,-1)],10,j),(e(),m(te,{to:`body`},[B.value?(e(),u(`div`,{key:0,ref_key:`popoverEl`,ref:V,style:h(G.value),class:`bg-panel border border-border rounded-lg shadow-xl p-3 text-xs`,onClick:r[1]||=w(()=>{},[`stop`])},[c(`div`,M,[r[4]||=c(`span`,{class:`text-textMuted`},`勾选已有,或新建:`,-1),c(`button`,{type:`button`,class:`text-textMuted hover:text-textMain`,onClick:J,title:`关闭`},[y(g(C),{class:`w-3.5 h-3.5`})])]),c(`div`,N,[g(k).tags.length>0?(e(!0),u(o,{key:0},n(g(k).tags,t=>(e(),u(`button`,{key:t.id,type:`button`,onClick:e=>ie(t.id),class:l([`inline-flex items-center px-2 py-0.5 rounded border transition-colors`,z.value.includes(t.id)?`${g(O)(t.color)} ring-1 ring-primary/40`:`bg-base text-textMuted border-border hover:text-textMain hover:border-textMuted/40`])},[z.value.includes(t.id)?(e(),m(g(x),{key:0,class:`w-3 h-3 mr-1`})):(e(),m(g(T),{key:1,class:`w-3 h-3 mr-1`})),v(` `+f(t.name),1)],10,P))),128)):(e(),u(`span`,F,`还没有任何标签,请在下方输入新建。`))]),c(`form`,{class:`flex items-center gap-1.5`,onSubmit:w(oe,[`prevent`])},[ee(c(`input`,{"onUpdate:modelValue":r[0]||=e=>U.value=e,type:`text`,maxlength:`30`,placeholder:`输入新标签名,回车创建`,class:`flex-1 min-w-0 bg-base border border-border rounded px-2 py-1 text-xs text-textMain placeholder-textMuted/60 focus:outline-none focus:border-primary/60`},null,512),[[ne,U.value]]),c(`button`,{type:`submit`,class:`inline-flex items-center px-2 py-1 rounded bg-primary/15 text-primary border border-primary/40 hover:bg-primary/25 disabled:opacity-50 disabled:cursor-not-allowed`,disabled:!U.value.trim()||W.value,title:`新建并添加`},[y(g(S),{class:`w-3 h-3 mr-0.5`}),r[5]||=v(` 添加 `,-1)],8,I)],32)],4)):d(``,!0)]))]))}});export{T as a,k as i,E as n,O as r,L as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{A as e,D as t,F as n,M as r,U as i,V as a,b as ee,c as o,f as s,ft as c,h as l,m as u,mt as d,n as te,p as f,q as p,t as m,v as h,y as g}from"./createLucideIcon-BmsTm7z-.js";import{t as _}from"./activity-DZCOq6kQ.js";import{t as ne}from"./copy-CNXWZJbC.js";import{t as re}from"./eye-off-BNUfzp8P.js";import{t as ie}from"./eye-vRDqRzR9.js";import{t as ae}from"./hard-drive-DBiQxkNS.js";import{n as v,t as y}from"./save-D0NTjP8Q.js";import{i as oe,n as se,r as ce,t as b}from"./sun-Cg6PdQms.js";import{t as x}from"./plus-CcefsCv_.js";import{t as S}from"./refresh-cw-OqaxwQhF.js";import{t as le}from"./server-DFHpqwVn.js";import{t as ue}from"./terminal-CUz5b_ol.js";import{c as de,g as C,i as w,p as fe,r as pe,s as T,v as me,y as he}from"./index-BZU6i5nw.js";var ge=m(`heart-pulse`,[[`path`,{d:`M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5`,key:`mvr1a0`}],[`path`,{d:`M3.22 13H9.5l.5-1 2 4.5 2-7 1.5 3.5h5.27`,key:`auskq0`}]]),_e=m(`webhook`,[[`path`,{d:`M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2`,key:`q3hayz`}],[`path`,{d:`m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06`,key:`1go1hn`}],[`path`,{d:`m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8`,key:`qlwsc0`}]]),ve={class:`max-w-4xl mx-auto space-y-6 pb-12 p-4 sm:p-0`},ye={class:`flex items-center space-x-3 mb-8`},be={class:`bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},xe={class:`px-4 sm:px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02]`},Se={class:`text-lg font-semibold text-textMain flex items-center`},Ce={class:`p-4 sm:p-6`},we={key:0,class:`grid grid-cols-2 md:grid-cols-4 gap-4`},Te={class:`bg-base border border-border rounded-lg p-4 text-center`},Ee={class:`text-2xl font-bold text-primary`},E={class:`bg-base border border-border rounded-lg p-4 text-center`},D={class:`text-2xl font-bold text-textMain`},De={class:`bg-base border border-border rounded-lg p-4 text-center`},Oe={class:`text-2xl font-bold text-textMain`},ke={class:`bg-base border border-border rounded-lg p-4 text-center`},Ae={class:`text-2xl font-bold text-textMain`},je={class:`bg-base border border-border rounded-lg p-4 text-center`},Me={class:`text-2xl font-bold text-success`},Ne={class:`bg-base border border-border rounded-lg p-4 text-center`},Pe={class:`text-2xl font-bold text-danger`},Fe={class:`bg-base border border-border rounded-lg p-4 text-center col-span-2`},Ie={class:`flex items-center justify-center space-x-2`},Le={class:`text-2xl font-bold text-textMain`},Re={key:1,class:`text-textMuted text-sm py-4 text-center`},ze={class:`bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},Be={class:`px-4 sm:px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02] flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3`},Ve={class:`text-lg font-semibold text-textMain flex items-center`},He=[`disabled`],Ue={class:`p-4 sm:p-6`},We={key:0,class:`text-textMuted text-sm py-4 text-center`},Ge={key:1,class:`text-textMuted text-sm py-4 text-center`},Ke={key:2,class:`grid grid-cols-2 md:grid-cols-4 gap-4`},qe={class:`bg-base border border-border rounded-lg p-4`},Je={class:`flex items-center justify-between mb-1`},Ye=[`title`],Xe={class:`text-xs text-textMuted mt-1`},Ze={class:`bg-base border border-border rounded-lg p-4`},Qe={class:`flex items-center justify-between mb-1`},$e=[`title`],et={class:`text-xs text-textMuted mt-1`},tt={class:`bg-base border border-border rounded-lg p-4`},nt={class:`flex items-center justify-between mb-1`},rt={class:`text-xs text-textMuted mt-1`},it={class:`bg-base border border-border rounded-lg p-4`},at={class:`flex items-center justify-between mb-1`},ot={class:`text-sm font-mono text-textMain`},st={class:`text-xs text-textMuted mt-1`},ct={class:`bg-base border border-border rounded-lg p-4 col-span-2`},lt={class:`text-sm font-mono text-textMain`},ut={class:`text-xs text-textMuted mt-1`},dt={class:`bg-base border border-border rounded-lg p-4 col-span-2`},ft={class:`text-sm font-mono text-textMain`},pt={class:`text-xs text-textMuted mt-1`},mt={class:`bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},ht={class:`px-4 sm:px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02]`},gt={class:`text-lg font-semibold text-textMain flex items-center`},_t={class:`p-4 sm:p-6`},vt={class:`grid grid-cols-1 sm:grid-cols-3 gap-3`},yt=[`onClick`],bt={class:`text-xs text-textMuted mt-1`},xt={class:`bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},St={class:`px-4 sm:px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02]`},Ct={class:`text-lg font-semibold text-textMain flex items-center`},wt={class:`p-4 sm:p-6 space-y-4`},Tt={class:`pt-2 flex justify-end`},Et={class:`bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},Dt={class:`px-4 sm:px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02]`},Ot={class:`text-lg font-semibold text-textMain flex items-center`},kt={class:`p-4 sm:p-6 space-y-4`},At={class:`flex gap-2`},O={class:`relative flex-1`},jt=[`type`],Mt=[`disabled`],Nt={class:`bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},Pt={class:`px-4 sm:px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02]`},Ft={class:`text-lg font-semibold text-textMain flex items-center`},It={class:`p-4 sm:p-6 space-y-4`},Lt={class:`flex flex-wrap gap-3`},Rt=[`onClick`],zt={class:`bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},Bt={class:`px-4 sm:px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02] flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3`},Vt={class:`text-lg font-semibold text-textMain flex items-center`},Ht=[`disabled`],Ut={class:`p-4 sm:p-6 space-y-4`},Wt={key:0,class:`flex items-start gap-2 text-sm text-yellow-500 bg-yellow-500/10 border border-yellow-500/30 rounded-md p-3`},Gt={class:`bg-base border border-border rounded-md p-4`},Kt={class:`flex flex-col sm:flex-row sm:items-center justify-between gap-3`},qt={class:`text-sm`},Jt={class:`font-mono text-textMain mt-1`},Yt={key:0,class:`text-xs text-textMuted mt-1`},Xt=[`disabled`],Zt={class:`flex gap-2`},Qt={class:`block text-sm font-medium text-textMain mb-2`},$t={key:0,class:`ml-2 text-xs text-yellow-500 font-normal`},en={key:0,class:`text-sm text-textMuted py-3`},tn={key:1,class:`space-y-1.5`},nn={class:`font-mono text-sm text-textMain truncate`},rn=[`onClick`],an={class:`flex items-center justify-end gap-3 pt-2`},on=[`disabled`],sn={class:`flex items-center justify-end space-x-4 pt-4`},cn=[`disabled`],k=ee({__name:`Settings`,setup(ee){let m=te(),k=de(),ln=[{value:`light`,label:`浅色模式`,icon:b,desc:`始终使用浅色主题`},{value:`dark`,label:`深色模式`,icon:ce,desc:`始终使用深色主题`},{value:`system`,label:`跟随系统`,icon:oe,desc:`自动匹配系统外观设置`}],A=i(null),j=i(null),M=i(!1),N=async()=>{M.value=!0,j.value=await m.fetchHealthDetail(),M.value=!1},un=e=>{if(e==null)return`N/A`;let t=e/1024/1024/1024;return t>=1?`${t.toFixed(2)} GB`:`${(e/1024/1024).toFixed(1)} MB`},P=e=>e==null?`text-textMuted`:e>=95?`text-danger`:e>=85?`text-yellow-400`:`text-success`,F=i({webhook_url:``,webhook_events:[],default_deploy_path:``,max_upload_size:`50`,global_deploy_token:``,artifact_keep_n:`10`,deployment_stuck_threshold_min:`10`}),I=i(!1),L=i(!1),dn=()=>{F.value.global_deploy_token&&(navigator.clipboard.writeText(F.value.global_deploy_token),L.value=!0,setTimeout(()=>L.value=!1,2e3))},R=i({oldToken:``,newToken:``,confirmPassword:``}),z=i(``),B=i(`success`),V=i(!1),H=i(``),fn=[{key:`deploy_success`,label:`部署成功`},{key:`deploy_failure`,label:`部署失败`}];t(async()=>{let[e,t]=await Promise.all([m.fetchSettings(),m.fetchSystemStatus()]);A.value=t,e&&(F.value.webhook_url=e.webhook_url||``,F.value.webhook_events=e.webhook_events?e.webhook_events.split(`,`):[],F.value.default_deploy_path=e.default_deploy_path||``,F.value.max_upload_size=e.max_upload_size||`50`,F.value.global_deploy_token=e.global_deploy_token||``,F.value.artifact_keep_n=e.artifact_keep_n||`10`,F.value.deployment_stuck_threshold_min=e.deployment_stuck_threshold_min||`10`),N(),Z()});let pn=async()=>{V.value=!0,H.value=``;let e=Number(F.value.deployment_stuck_threshold_min);if(!Number.isInteger(e)||e<1||e>1440){H.value=`卡死阈值需在 1~1440 分钟之间`,V.value=!1,setTimeout(()=>H.value=``,3e3);return}H.value=await m.updateSettings({webhook_url:F.value.webhook_url,webhook_events:F.value.webhook_events.join(`,`),default_deploy_path:F.value.default_deploy_path,max_upload_size:F.value.max_upload_size,global_deploy_token:F.value.global_deploy_token,artifact_keep_n:F.value.artifact_keep_n,deployment_stuck_threshold_min:String(e)})?`保存成功`:`保存失败`,V.value=!1,setTimeout(()=>H.value=``,3e3)},mn=async()=>{if(z.value=``,R.value.newToken!==R.value.confirmPassword){z.value=`两次输入的新 Token 不一致`,B.value=`error`;return}if(R.value.newToken.length<8){z.value=`新 Token 长度不能少于 8 位`,B.value=`error`;return}let e=await m.changeAdminToken(R.value.oldToken,R.value.newToken);e.success?(z.value=e.message||`Token 已更新`,B.value=`success`,R.value={oldToken:``,newToken:``,confirmPassword:``}):(z.value=e.error||`修改失败`,B.value=`error`)},hn=()=>{let e=crypto.randomUUID().replace(/-/g,``);F.value.global_deploy_token=`kt_${e}`},gn=e=>{let t=F.value.webhook_events.indexOf(e);t>=0?F.value.webhook_events.splice(t,1):F.value.webhook_events.push(e)},U=i([]),W=i(``),G=i(``),K=i(`success`),q=i(!1),J=i(!1),Y=i(null),X=i(null);async function Z(){J.value=!0;let[e,t,n]=await Promise.all([m.fetchTerminalAllowlist(),m.fetchTerminalWhoami(),m.fetchTerminalInfo()]);e&&(U.value=e.entries),Y.value=t,X.value=n?.available??null,J.value=!1}function Q(e,t){G.value=e,K.value=t,setTimeout(()=>{G.value=``},3e3)}function $(e){let t=(e??W.value).trim();if(t){if(U.value.includes(t)){Q(`该 IP / CIDR 已在白名单中`,`error`);return}U.value=[...U.value,t],W.value=``}}function _n(e){U.value=U.value.filter(t=>t!==e)}async function vn(){q.value=!0;let e=await m.updateTerminalAllowlist(U.value);q.value=!1,e.success?(e.entries&&(U.value=e.entries),Q(`已保存终端 IP 白名单`,`success`)):Q(e.error||`保存失败`,`error`)}function yn(){let e=Y.value?.trustedIp||Y.value?.socketIp;if(!e){Q(`当前访问 IP 未知`,`error`);return}$(e)}return(t,i)=>(e(),l(`div`,ve,[s(`div`,ye,[g(p(se),{class:`w-7 h-7 text-primary`}),i[13]||=s(`h1`,{class:`text-2xl font-bold text-textMain tracking-tight`},`系统设置`,-1)]),s(`div`,be,[s(`div`,xe,[s(`h2`,Se,[g(p(le),{class:`w-5 h-5 mr-2 text-primary`}),i[14]||=h(` 系统信息 `,-1)])]),s(`div`,Ce,[A.value?(e(),l(`div`,we,[s(`div`,Te,[s(`p`,Ee,d(A.value.version),1),i[15]||=s(`p`,{class:`text-xs text-textMuted mt-1`},`版本号`,-1)]),s(`div`,E,[s(`p`,D,d(A.value.uptime),1),i[16]||=s(`p`,{class:`text-xs text-textMuted mt-1`},`运行时间`,-1)]),s(`div`,De,[s(`p`,Oe,d(A.value.projectCount),1),i[17]||=s(`p`,{class:`text-xs text-textMuted mt-1`},`项目总数`,-1)]),s(`div`,ke,[s(`p`,Ae,d(A.value.deploymentCount),1),i[18]||=s(`p`,{class:`text-xs text-textMuted mt-1`},`部署总次数`,-1)]),s(`div`,je,[s(`p`,Me,d(A.value.successCount),1),i[19]||=s(`p`,{class:`text-xs text-textMuted mt-1`},`成功部署`,-1)]),s(`div`,Ne,[s(`p`,Pe,d(A.value.failedCount),1),i[20]||=s(`p`,{class:`text-xs text-textMuted mt-1`},`失败次数`,-1)]),s(`div`,Fe,[s(`div`,Ie,[g(p(_),{class:`w-5 h-5 text-primary`}),s(`p`,Le,d(A.value.successRate)+`%`,1)]),i[21]||=s(`p`,{class:`text-xs text-textMuted mt-1`},`部署成功率`,-1)])])):(e(),l(`div`,Re,`加载中...`))])]),s(`div`,ze,[s(`div`,Be,[s(`div`,null,[s(`h2`,Ve,[g(p(ge),{class:`w-5 h-5 mr-2 text-primary`}),i[22]||=h(` 服务健康 `,-1)]),i[23]||=s(`p`,{class:`text-sm text-textMuted mt-1`},[h(`实时探活 DB、磁盘、Kite Home 与最近部署成功率,等同 `),s(`code`,{class:`font-mono text-primary`},`kite doctor`),h(` 远端段。`)],-1)]),s(`button`,{onClick:N,disabled:M.value,class:`self-start sm:self-auto flex items-center px-3 py-2 bg-base border border-border rounded-md text-textMuted hover:text-textMain hover:border-primary/50 transition-all disabled:opacity-50`,type:`button`},[g(p(S),{class:c([`w-4 h-4`,M.value?`animate-spin`:``])},null,8,[`class`])],8,He)]),s(`div`,Ue,[!j.value&&!M.value?(e(),l(`div`,We,`暂无数据`)):M.value&&!j.value?(e(),l(`div`,Ge,`加载中...`)):(e(),l(`div`,Ke,[s(`div`,qe,[s(`div`,Je,[i[24]||=s(`p`,{class:`text-xs text-textMuted`},`DB`,-1),j.value.db?.ok?(e(),f(p(T),{key:0,class:`w-4 h-4 text-success`})):(e(),f(p(w),{key:1,class:`w-4 h-4 text-danger`}))]),s(`p`,{class:`text-sm font-mono text-textMain truncate`,title:j.value.db?.path},d(j.value.db?.path||`N/A`),9,Ye),s(`p`,Xe,d(j.value.db?.latencyMs??`?`)+` ms`,1)]),s(`div`,Ze,[s(`div`,Qe,[i[25]||=s(`p`,{class:`text-xs text-textMuted`},`Kite Home`,-1),j.value.kiteHome?.writable?(e(),f(p(T),{key:0,class:`w-4 h-4 text-success`})):(e(),f(p(w),{key:1,class:`w-4 h-4 text-danger`}))]),s(`p`,{class:`text-sm font-mono text-textMain truncate`,title:j.value.kiteHome?.path},d(j.value.kiteHome?.path||`N/A`),9,$e),s(`p`,et,`tmp `+d(j.value.kiteHome?.tmpWritable?`可写`:`不可写`),1)]),s(`div`,tt,[s(`div`,nt,[i[26]||=s(`p`,{class:`text-xs text-textMuted`},`磁盘`,-1),g(p(_),{class:c([`w-4 h-4`,P(j.value.disk?.percentUsed)])},null,8,[`class`])]),s(`p`,{class:c([`text-sm font-mono`,P(j.value.disk?.percentUsed)])},d(j.value.disk?.percentUsed==null?`N/A`:j.value.disk.percentUsed+`%`),3),s(`p`,rt,d(un(j.value.disk?.freeBytes))+` 可用`,1)]),s(`div`,it,[s(`div`,at,[i[27]||=s(`p`,{class:`text-xs text-textMuted`},`最近 5 次部署`,-1),g(p(_),{class:`w-4 h-4 text-primary`})]),s(`p`,ot,d(j.value.deploy?.successRate==null?`N/A`:Math.round(j.value.deploy.successRate*100)+`%`),1),s(`p`,st,`共 `+d(j.value.deploy?.last5?.length??0)+` 条`,1)]),s(`div`,ct,[i[28]||=s(`p`,{class:`text-xs text-textMuted mb-1`},`Runtime`,-1),s(`p`,lt,d(j.value.runtime?.name)+` `+d(j.value.runtime?.version),1),s(`p`,ut,`uptime `+d(j.value.uptimeSec)+`s · 内存 RSS `+d(j.value.memoryMB?.rss)+`MB / Heap `+d(j.value.memoryMB?.heapUsed)+`MB`,1)]),s(`div`,dt,[i[29]||=s(`p`,{class:`text-xs text-textMuted mb-1`},`服务器时间`,-1),s(`p`,ft,d(j.value.serverTime),1),s(`p`,pt,`version `+d(j.value.version),1)])]))])]),s(`div`,mt,[s(`div`,ht,[s(`h2`,gt,[g(p(b),{class:`w-5 h-5 mr-2 text-primary`}),i[30]||=h(` 外观设置 `,-1)]),i[31]||=s(`p`,{class:`text-sm text-textMuted mt-1`},`选择界面的色彩方案,或跟随系统自动切换。`,-1)]),s(`div`,_t,[s(`div`,vt,[(e(),l(o,null,r(ln,t=>s(`button`,{key:t.value,onClick:e=>p(k).setMode(t.value),class:c([`relative flex flex-col items-center p-4 rounded-lg border-2 transition-all`,p(k).mode===t.value?`border-primary bg-primary/5 shadow-[0_0_12px_rgba(59,130,246,0.15)]`:`border-border hover:border-textMuted/50 bg-base`])},[(e(),f(n(t.icon),{class:c([`w-6 h-6 mb-2`,p(k).mode===t.value?`text-primary`:`text-textMuted`])},null,8,[`class`])),s(`span`,{class:c([`text-sm font-medium`,p(k).mode===t.value?`text-primary`:`text-textMain`])},d(t.label),3),s(`span`,bt,d(t.desc),1),p(k).mode===t.value?(e(),f(p(T),{key:0,class:`absolute top-2 right-2 w-4 h-4 text-primary`})):u(``,!0)],10,yt)),64))])])]),s(`div`,xt,[s(`div`,St,[s(`h2`,Ct,[g(p(v),{class:`w-5 h-5 mr-2 text-primary`}),i[32]||=h(` 管理员 Token `,-1)]),i[33]||=s(`p`,{class:`text-sm text-textMuted mt-1`},`修改管理后台的登录凭证。修改后需使用新 Token 重新登录。`,-1)]),s(`div`,wt,[s(`div`,null,[i[34]||=s(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`当前 Token`,-1),a(s(`input`,{"onUpdate:modelValue":i[0]||=e=>R.value.oldToken=e,type:`password`,class:`w-full bg-base border border-border rounded-md px-4 py-3 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`请输入当前 Token`},null,512),[[C,R.value.oldToken]])]),s(`div`,null,[i[35]||=s(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`新 Token`,-1),a(s(`input`,{"onUpdate:modelValue":i[1]||=e=>R.value.newToken=e,type:`password`,class:`w-full bg-base border border-border rounded-md px-4 py-3 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`请输入新 Token(至少 8 位)`},null,512),[[C,R.value.newToken]])]),s(`div`,null,[i[36]||=s(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`确认新 Token`,-1),a(s(`input`,{"onUpdate:modelValue":i[2]||=e=>R.value.confirmPassword=e,type:`password`,class:`w-full bg-base border border-border rounded-md px-4 py-3 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`请再次输入新 Token`},null,512),[[C,R.value.confirmPassword]])]),z.value?(e(),l(`div`,{key:0,class:c([`flex items-center space-x-2 text-sm`,B.value===`success`?`text-success`:`text-danger`])},[B.value===`success`?(e(),f(p(T),{key:0,class:`w-4 h-4`})):(e(),f(p(w),{key:1,class:`w-4 h-4`})),s(`span`,null,d(z.value),1)],2)):u(``,!0),s(`div`,Tt,[s(`button`,{onClick:mn,class:`flex items-center px-6 py-2.5 bg-primary hover:bg-primary/90 text-white rounded-md transition-all font-medium shadow-[0_0_15px_rgba(59,130,246,0.3)]`},[g(p(v),{class:`w-4 h-4 mr-2`}),i[37]||=h(` 修改 Token `,-1)])])])]),s(`div`,Et,[s(`div`,Dt,[s(`h2`,Ot,[g(p(ae),{class:`w-5 h-5 mr-2 text-primary`}),i[38]||=h(` 全局部署配置 `,-1)]),i[39]||=s(`p`,{class:`text-sm text-textMuted mt-1`},`设置全局默认的部署参数,可在项目级别覆盖。`,-1)]),s(`div`,kt,[s(`div`,null,[i[40]||=s(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`全局部署 Token`,-1),s(`div`,At,[s(`div`,O,[a(s(`input`,{"onUpdate:modelValue":i[3]||=e=>F.value.global_deploy_token=e,type:I.value?`text`:`password`,class:`w-full bg-base border border-border rounded-md px-4 py-3 pr-10 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`留空则不启用全局 Token`},null,8,jt),[[fe,F.value.global_deploy_token]]),s(`button`,{onClick:i[4]||=e=>I.value=!I.value,class:`absolute right-3 top-1/2 -translate-y-1/2 text-textMuted hover:text-textMain transition-colors`,type:`button`},[I.value?(e(),f(p(re),{key:0,class:`w-4 h-4`})):(e(),f(p(ie),{key:1,class:`w-4 h-4`}))])]),s(`button`,{onClick:hn,class:`flex items-center px-3 bg-base border border-border rounded-md text-textMuted hover:text-textMain hover:border-primary/50 transition-all`,title:`生成随机 Token`,type:`button`},[g(p(S),{class:`w-4 h-4`})]),s(`button`,{onClick:dn,disabled:!F.value.global_deploy_token,class:`flex items-center px-3 bg-base border border-border rounded-md text-textMuted hover:text-textMain hover:border-primary/50 transition-all disabled:opacity-50 disabled:cursor-not-allowed`,title:`复制 Token`,type:`button`},[L.value?(e(),f(p(T),{key:0,class:`w-4 h-4 text-success`})):(e(),f(p(ne),{key:1,class:`w-4 h-4`}))],8,Mt)]),i[41]||=s(`p`,{class:`text-xs text-textMuted mt-2`},`所有项目共用的部署 Token。CLI 使用全局 Token 时,配合 --project 指定项目即可部署,无需为每个项目单独配置 Token。留空则禁用。`,-1)]),s(`div`,null,[i[42]||=s(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`默认部署路径`,-1),a(s(`input`,{"onUpdate:modelValue":i[5]||=e=>F.value.default_deploy_path=e,type:`text`,class:`w-full bg-base border border-border rounded-md px-4 py-3 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`e.g. .deployments`},null,512),[[C,F.value.default_deploy_path]]),i[43]||=s(`p`,{class:`text-xs text-textMuted mt-2`},`新项目创建时的默认部署目录(相对于工作目录)。`,-1)]),s(`div`,null,[i[44]||=s(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`最大上传大小 (MB)`,-1),a(s(`input`,{"onUpdate:modelValue":i[6]||=e=>F.value.max_upload_size=e,type:`number`,min:`1`,max:`500`,class:`w-full bg-base border border-border rounded-md px-4 py-3 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`50`},null,512),[[C,F.value.max_upload_size]]),i[45]||=s(`p`,{class:`text-xs text-textMuted mt-2`},`单次部署上传的 ZIP 文件大小上限。`,-1)]),s(`div`,null,[i[46]||=s(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`归档保留份数 (artifact_keep_n)`,-1),a(s(`input`,{"onUpdate:modelValue":i[7]||=e=>F.value.artifact_keep_n=e,type:`number`,min:`1`,max:`500`,class:`w-full bg-base border border-border rounded-md px-4 py-3 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`10`},null,512),[[C,F.value.artifact_keep_n]]),i[47]||=s(`p`,{class:`text-xs text-textMuted mt-2`},[h(` 每个项目保留最近多少份部署归档 ZIP(位于 `),s(`code`,{class:`font-mono text-textMain`},`~/.kite/deployments/<projectId>/artifacts/`),h(`),超出部分按时间倒序清理。 归档保留越多,可回滚的历史越长,占用磁盘也越大。被任何 `),s(`code`,{class:`font-mono text-textMain`},`rollback`),h(` 引用的归档不会被清理。 `)],-1)]),s(`div`,null,[i[48]||=s(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`卡死部署阈值 (分钟)`,-1),a(s(`input`,{"onUpdate:modelValue":i[8]||=e=>F.value.deployment_stuck_threshold_min=e,type:`number`,min:`1`,max:`1440`,class:`w-full bg-base border border-border rounded-md px-4 py-3 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`10`},null,512),[[C,F.value.deployment_stuck_threshold_min]]),i[49]||=s(`p`,{class:`text-xs text-textMuted mt-2`},[h(` 部署日志页面中,运行时长超过该分钟数的"进行中"部署会显示`),s(`strong`,{class:`text-textMain`},`「标记为成功 / 失败」`),h(`按钮,用于修正服务异常退出残留的状态。范围 1~1440,默认 10。 `)],-1)])])]),s(`div`,Nt,[s(`div`,Pt,[s(`h2`,Ft,[g(p(_e),{class:`w-5 h-5 mr-2 text-primary`}),i[50]||=h(` Webhook 通知 `,-1)]),i[51]||=s(`p`,{class:`text-sm text-textMuted mt-1`},`部署事件发生时,向指定 URL 发送 POST 通知。`,-1)]),s(`div`,It,[s(`div`,null,[i[52]||=s(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`Webhook URL`,-1),a(s(`input`,{"onUpdate:modelValue":i[9]||=e=>F.value.webhook_url=e,type:`url`,class:`w-full bg-base border border-border rounded-md px-4 py-3 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`https://example.com/webhook`},null,512),[[C,F.value.webhook_url]]),i[53]||=s(`p`,{class:`text-xs text-textMuted mt-2`},`留空则不发送通知。支持飞书、钉钉、Slack 等标准 Webhook。`,-1)]),s(`div`,null,[i[54]||=s(`label`,{class:`block text-sm font-medium text-textMain mb-3`},`触发事件`,-1),s(`div`,Lt,[(e(),l(o,null,r(fn,t=>s(`button`,{key:t.key,onClick:e=>gn(t.key),class:c([`flex items-center px-4 py-2 rounded-md text-sm font-medium border transition-all`,F.value.webhook_events.includes(t.key)?`bg-primary/10 border-primary/30 text-primary`:`bg-base border-border text-textMuted hover:border-primary/30 hover:text-textMain`])},[F.value.webhook_events.includes(t.key)?(e(),f(p(T),{key:0,class:`w-4 h-4 mr-2`})):u(``,!0),h(` `+d(t.label),1)],10,Rt)),64))])])])]),s(`div`,zt,[s(`div`,Bt,[s(`div`,null,[s(`h2`,Vt,[g(p(ue),{class:`w-5 h-5 mr-2 text-primary`}),i[55]||=h(` 终端 IP 白名单 `,-1)]),i[56]||=s(`p`,{class:`text-sm text-textMuted mt-1`},[h(` 限制可使用 Web 终端的来源 IP。留空表示`),s(`strong`,{class:`text-textMain`},`不启用`),h(`白名单(任何已登录用户均可使用)。支持 IPv4、IPv6、CIDR 表示。 `)],-1)]),s(`button`,{onClick:Z,class:`flex items-center px-3 py-1.5 text-sm bg-base border border-border hover:border-primary/50 hover:text-primary text-textMuted rounded-md transition-all self-start sm:self-auto`,disabled:J.value},[g(p(S),{class:c([`w-4 h-4 mr-1.5`,J.value?`animate-spin`:``])},null,8,[`class`]),i[57]||=h(` 刷新 `,-1)],8,Ht)]),s(`div`,Ut,[X.value===!1?(e(),l(`div`,Wt,[g(p(w),{class:`w-4 h-4 mt-0.5 shrink-0`}),i[58]||=s(`span`,null,`当前实例的终端能力不可用(仅 macOS / Linux + node-pty 可用)。即便配置白名单也无法使用 Web 终端。`,-1)])):u(``,!0),s(`div`,Gt,[s(`div`,Kt,[s(`div`,qt,[i[59]||=s(`div`,{class:`text-textMuted`},`当前访问 IP`,-1),s(`div`,Jt,d(Y.value?.trustedIp||Y.value?.socketIp||`未知`),1),Y.value?.forwardedIp&&Y.value.forwardedIp!==Y.value.trustedIp?(e(),l(`div`,Yt,` XFF 头声明:`+d(Y.value.forwardedIp)+`(不被信任,仅供参考) `,1)):u(``,!0)]),s(`button`,{onClick:yn,disabled:!Y.value?.trustedIp&&!Y.value?.socketIp,class:`flex items-center px-3 py-2 text-sm bg-primary/10 hover:bg-primary/20 text-primary border border-primary/30 rounded-md transition-all disabled:opacity-50`},[g(p(x),{class:`w-4 h-4 mr-1.5`}),i[60]||=h(` 加入白名单 `,-1)],8,Xt)])]),s(`div`,null,[i[62]||=s(`label`,{class:`block text-sm font-medium text-textMain mb-2`},`添加 IP / CIDR`,-1),s(`div`,Zt,[a(s(`input`,{"onUpdate:modelValue":i[10]||=e=>W.value=e,type:`text`,class:`flex-1 bg-base border border-border rounded-md px-4 py-2.5 text-textMain font-mono text-sm focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/50 transition-all`,placeholder:`例如 192.168.1.0/24 或 ::1`,onKeydown:i[11]||=me(he(e=>$(),[`prevent`]),[`enter`])},null,544),[[C,W.value]]),s(`button`,{onClick:i[12]||=e=>$(),class:`flex items-center px-4 py-2.5 bg-base border border-border hover:border-primary/50 hover:text-primary text-textMuted rounded-md transition-all`},[g(p(x),{class:`w-4 h-4 mr-1.5`}),i[61]||=h(` 添加 `,-1)])])]),s(`div`,null,[s(`label`,Qt,[h(` 当前白名单(`+d(U.value.length)+` 条) `,1),U.value.length===0?(e(),l(`span`,$t,`空 = 不启用白名单`)):u(``,!0)]),U.value.length===0?(e(),l(`div`,en,` 暂无条目。 `)):(e(),l(`ul`,tn,[(e(!0),l(o,null,r(U.value,t=>(e(),l(`li`,{key:t,class:`flex items-center justify-between gap-2 bg-base border border-border rounded-md px-3 py-2`},[s(`span`,nn,d(t),1),s(`button`,{onClick:e=>_n(t),class:`p-1 text-textMuted hover:text-danger rounded transition-colors`,title:`移除`},[g(p(pe),{class:`w-4 h-4`})],8,rn)]))),128))]))]),s(`div`,an,[G.value?(e(),l(`span`,{key:0,class:c([`text-sm`,K.value===`success`?`text-success`:`text-danger`])},d(G.value),3)):u(``,!0),s(`button`,{onClick:vn,disabled:q.value,class:`flex items-center px-5 py-2 bg-primary hover:bg-primary/90 text-white rounded-md transition-all font-medium disabled:opacity-50`},[g(p(y),{class:`w-4 h-4 mr-2`}),h(` `+d(q.value?`保存中...`:`保存白名单`),1)],8,on)])])]),s(`div`,sn,[H.value?(e(),l(`span`,{key:0,class:c([`text-sm`,H.value===`保存成功`?`text-success`:`text-danger`])},d(H.value),3)):u(``,!0),s(`button`,{onClick:pn,disabled:V.value,class:`flex items-center px-6 py-2.5 bg-primary hover:bg-primary/90 text-white rounded-md transition-all font-medium shadow-[0_0_15px_rgba(59,130,246,0.3)] disabled:opacity-50`},[g(p(y),{class:`w-4 h-4 mr-2`}),h(` `+d(V.value?`保存中...`:`保存配置`),1)],8,cn)])]))}});export{k as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{A as e,B as t,D as n,F as r,M as i,U as a,b as ee,c as o,d as s,f as c,ft as l,h as u,m as d,mt as f,n as te,p as ne,pt as p,q as m,v as h,y as g}from"./createLucideIcon-BmsTm7z-.js";import{t as re}from"./archive-MB1JcYug.js";import{n as ie,t as ae}from"./file-text-BxWt6is5.js";import{t as oe}from"./database-D6rC_24l.js";import{t as se}from"./folder-CYPJgLMr.js";import{t as ce}from"./hard-drive-DBiQxkNS.js";import{t as le}from"./refresh-cw-OqaxwQhF.js";import{t as ue}from"./trash-2-20ikd6fk.js";import{d as de,i as fe,n as pe,r as me,s as he,t as _,y as ge}from"./index-BZU6i5nw.js";import{t as _e}from"./ConfirmDialog-CikXU818.js";var ve={class:`space-y-6 p-4 sm:p-0`},ye={class:`flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3`},be={class:`text-2xl font-bold text-textMain flex items-center`},xe=[`disabled`],Se={key:0,class:`bg-danger/10 border border-danger/30 text-danger text-sm rounded-lg px-4 py-3`},v={class:`bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},y={class:`px-4 sm:px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02]`},b={class:`text-sm text-textMuted mt-1`},x={key:0,class:`text-yellow-400`},S={key:1,class:`text-yellow-400 inline-flex items-center`},C={key:2,class:`text-textMuted`},w={key:0,class:`p-4 sm:p-6 text-textMuted text-sm text-center`},T={key:1,class:`p-4 sm:p-6 grid grid-cols-1 md:grid-cols-2 gap-6`},E={class:`flex items-baseline justify-between mb-3 gap-2`},D={class:`text-xs text-textMuted font-mono break-all`},O={class:`text-2xl font-bold text-textMain font-mono shrink-0`},k={class:`space-y-2`},A={class:`flex items-center justify-between text-xs`},j={class:`text-textMain inline-flex items-center`},Ce={class:`font-mono text-textMuted`},we={class:`h-1.5 bg-base rounded-full overflow-hidden`},Te={class:`flex items-baseline justify-between mb-3`},Ee={class:`text-2xl font-bold text-textMain font-mono`},De={class:`h-3 bg-base rounded-full overflow-hidden mb-3`},Oe={class:`grid grid-cols-2 gap-2 text-xs`},ke={class:`bg-base rounded-md px-3 py-2`},Ae={class:`font-mono text-textMain mt-0.5`},je={class:`bg-base rounded-md px-3 py-2`},Me={class:`font-mono text-textMain mt-0.5`},Ne={key:0,class:`text-xs text-textMuted mt-2 italic`},Pe={class:`bg-panel border border-border rounded-xl shadow-sm overflow-hidden`},Fe={key:0,class:`p-4 sm:p-6 text-textMuted text-sm text-center`},Ie={key:1,class:`overflow-x-auto`},Le={class:`w-full text-sm min-w-[720px]`},Re={class:`px-6 py-3`},ze={class:`text-textMain font-medium`},Be={class:`text-xs text-textMuted font-mono mt-0.5`},Ve={class:`px-4 py-3 text-right font-mono text-textMain`},He={class:`px-4 py-3 text-right font-mono text-textMuted`},Ue={class:`px-4 py-3 text-textMuted text-xs`},We={class:`px-4 py-3 text-right`},Ge={key:0,class:`font-mono text-textMain`},Ke={key:1,class:`text-textMuted text-xs italic`},qe={key:2,class:`text-[10px] text-textMuted font-mono truncate max-w-[180px] ml-auto mt-0.5`},Je={class:`px-6 py-3 text-right`},Ye=[`onClick`],Xe={class:`ml-auto relative w-full max-w-xl bg-panel border-l border-border h-full overflow-y-auto z-50`},Ze={class:`sticky top-0 bg-panel border-b border-border px-4 sm:px-6 py-4 flex items-center justify-between z-10`},Qe={class:`text-lg font-semibold text-textMain mt-0.5`},$e={class:`p-4 sm:p-6`},M={key:0,class:`text-textMuted text-sm text-center py-8`},et={key:1,class:`bg-danger/10 border border-danger/30 text-danger text-sm rounded-md px-3 py-2`},tt={key:2},nt={class:`bg-base border border-border rounded-md px-4 py-3 mb-4 flex items-center justify-between`},rt={class:`font-mono text-textMain`},it={key:0,class:`text-textMuted text-sm text-center py-6`},at={key:1,class:`space-y-2`},ot={class:`flex items-start justify-between gap-3`},st={class:`min-w-0 flex-1`},ct={class:`flex items-center gap-2 flex-wrap`},lt={class:`font-mono text-sm text-textMain`},ut={key:0,class:`px-1.5 py-0.5 text-[10px] font-mono rounded border bg-yellow-400/15 text-yellow-400 border-yellow-400/30`},dt={class:`text-xs text-textMuted mt-1.5 flex items-center gap-3`},ft={class:`font-mono`},pt={class:`shrink-0`},mt=[`onClick`],ht=[`title`],N=_(ee({__name:`Storage`,setup(ee){let _=te(),N=pe(),P=a(null),F=a([]),I=a(!1),L=a(``),R=a(!1),z=a(null),B=a(null),V=a(!1),H=a(``),U=a(!1),W=a(null),G=a(!1),K=e=>{if(e==null||!Number.isFinite(e))return`-`;if(e===0)return`0 B`;let t=[`B`,`KB`,`MB`,`GB`,`TB`],n=e,r=0;for(;n>=1024&&r<t.length-1;)n/=1024,r++;return`${n.toFixed(n>=100||r===0?0:n>=10?1:2)} ${t[r]}`},q=e=>{if(!e)return`-`;let t=new Date(e);if(Number.isNaN(t.getTime()))return e;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}`},J=s(()=>P.value?.kiteHome.totalBytes||0),gt=s(()=>{if(!P.value)return[];let e=P.value.kiteHome.breakdown,t=Math.max(J.value,1);return[{label:`deployments/`,value:e.deployments,color:`bg-primary`,icon:re},{label:`tmp/`,value:e.tmp,color:`bg-yellow-400`,icon:se},{label:`kite.db`,value:e.db,color:`bg-success`,icon:oe},{label:`config.json`,value:e.config,color:`bg-textMuted`,icon:ae}].map(e=>({...e,pct:e.value/t*100}))}),Y=s(()=>P.value?.filesystem.percentUsed??null),_t=s(()=>{let e=Y.value;return e==null?`bg-textMuted`:e>=95?`bg-danger`:e>=85?`bg-yellow-400`:`bg-success`}),X=async()=>{I.value=!0,L.value=``;try{let[e,t]=await Promise.all([_.fetchDiskOverview(),_.fetchDiskProjects()]);P.value=e,F.value=t.items}catch(e){L.value=e?.message||`加载失败`,N.error(L.value)}finally{I.value=!1}},Z=async e=>{z.value=e,R.value=!0,V.value=!0,H.value=``,B.value=null;try{B.value=await _.fetchProjectArtifacts(e.projectId)}catch(e){H.value=e?.message||`加载归档失败`}finally{V.value=!1}},Q=()=>{R.value=!1,z.value=null,B.value=null},vt=e=>{if(!e.canDelete){N.warning(`该归档被 ${e.referencedBy} 条部署记录引用,无法删除`);return}W.value=e,U.value=!0},yt=async()=>{if(W.value){G.value=!0;try{let e=await _.deleteArtifact(W.value.deployId);e?.success?(N.success(`已删除归档,释放 ${K(e.freedBytes)}`),z.value&&await Z(z.value),await X(),U.value=!1,W.value=null):N.error(e?.error||`删除失败`)}catch(e){e?.message?.includes(`referenced`)?N.warning(`该归档被其它部署记录引用`):N.error(e?.message||`删除失败`)}finally{G.value=!1}}},bt=()=>{U.value=!1,W.value=null},$=e=>{if(e.triggerSource===`rollback`)return{label:`rollback`,cls:`bg-yellow-400/15 text-yellow-400 border-yellow-400/30`};switch(e.status){case`success`:return{label:`success`,cls:`bg-success/15 text-success border-success/30`};case`failed`:return{label:`failed`,cls:`bg-danger/15 text-danger border-danger/30`};case`running`:return{label:`running`,cls:`bg-primary/15 text-primary border-primary/30`};default:return{label:e.status||`-`,cls:`bg-textMuted/15 text-textMuted border-border`}}},xt=s(()=>{if(!W.value)return``;let e=W.value;return`deployId: ${e.deployId}\n大小: ${K(e.sizeBytes)}\n创建时间: ${q(e.createdAt)}\n\n删除后该部署记录将无法回滚(仅清理归档 zip,部署记录保留)。`});return n(()=>{X()}),(n,a)=>(e(),u(`div`,ve,[c(`div`,ye,[c(`div`,null,[c(`h1`,be,[g(m(ce),{class:`w-6 h-6 mr-2 text-primary`}),a[1]||=h(` 存储 `,-1)]),a[2]||=c(`p`,{class:`text-sm text-textMuted mt-1`},`查看 Kite 数据目录与项目归档的磁盘占用,按需手动清理。`,-1)]),c(`button`,{onClick:X,disabled:I.value,class:`self-start sm:self-auto flex items-center px-3 py-2 bg-base border border-border rounded-md text-textMuted hover:text-textMain hover:border-primary/50 transition-all disabled:opacity-50`,type:`button`},[g(m(le),{class:l([`w-4 h-4 mr-2`,I.value?`animate-spin`:``])},null,8,[`class`]),a[3]||=h(` 刷新 `,-1)],8,xe)]),L.value?(e(),u(`div`,Se,f(L.value),1)):d(``,!0),c(`div`,v,[c(`div`,y,[a[5]||=c(`h2`,{class:`text-lg font-semibold text-textMain`},`~/.kite 数据目录`,-1),c(`p`,b,[P.value?.cached?(e(),u(`span`,x,`使用 30s 内缓存结果`)):P.value?.kiteHome.approximated?(e(),u(`span`,S,[g(m(fe),{class:`w-3.5 h-3.5 mr-1`}),a[4]||=h(` 目录较大,部分子目录扫描已超时(近似值) `,-1)])):(e(),u(`span`,C,`opendir 流式扫描,结果在内存中缓存 30s。`))])]),P.value?(e(),u(`div`,T,[c(`div`,null,[c(`div`,E,[c(`span`,D,f(P.value.kiteHome.path),1),c(`span`,O,f(K(J.value)),1)]),c(`div`,k,[(e(!0),u(o,null,i(gt.value,t=>(e(),u(`div`,{key:t.label,class:`space-y-1`},[c(`div`,A,[c(`span`,j,[(e(),ne(r(t.icon),{class:`w-3.5 h-3.5 mr-1.5 text-textMuted`})),h(` `+f(t.label),1)]),c(`span`,Ce,f(K(t.value)),1)]),c(`div`,we,[c(`div`,{class:l([`h-full`,t.color]),style:p({width:t.pct+`%`})},null,6)])]))),128))])]),c(`div`,null,[c(`div`,Te,[a[6]||=c(`span`,{class:`text-xs text-textMuted`},`系统盘(包含 Kite Home 所在挂载点)`,-1),c(`span`,Ee,[P.value.filesystem.percentUsed==null?(e(),u(o,{key:1},[h(`-`)],64)):(e(),u(o,{key:0},[h(f(P.value.filesystem.percentUsed)+`%`,1)],64))])]),c(`div`,De,[c(`div`,{class:l([`h-full transition-all`,_t.value]),style:p({width:(Y.value??0)+`%`})},null,6)]),c(`div`,Oe,[c(`div`,ke,[a[7]||=c(`div`,{class:`text-textMuted`},`可用`,-1),c(`div`,Ae,f(K(P.value.filesystem.freeBytes)),1)]),c(`div`,je,[a[8]||=c(`div`,{class:`text-textMuted`},`总容量`,-1),c(`div`,Me,f(K(P.value.filesystem.totalBytes)),1)])]),P.value.filesystem.percentUsed==null?(e(),u(`p`,Ne,` 当前平台未提供 df 信息(如 Windows)。 `)):d(``,!0)])])):(e(),u(`div`,w,`加载中...`))]),c(`div`,Pe,[a[11]||=c(`div`,{class:`px-4 sm:px-6 py-5 border-b border-border dark:bg-white/[0.02] bg-black/[0.02]`},[c(`h2`,{class:`text-lg font-semibold text-textMain`},`项目占用`),c(`p`,{class:`text-sm text-textMuted mt-1`},`归档 zip 由 keepN 策略自动清理,部署目录由你的部署模式决定(merge 累加 / clean 仅本次内容)。`)],-1),!I.value&&F.value.length===0?(e(),u(`div`,Fe,`暂无项目`)):(e(),u(`div`,Ie,[c(`table`,Le,[a[10]||=c(`thead`,{class:`text-xs text-textMuted bg-base/40 border-b border-border`},[c(`tr`,null,[c(`th`,{class:`text-left px-6 py-3 font-medium`},`项目`),c(`th`,{class:`text-right px-4 py-3 font-medium`},`归档大小`),c(`th`,{class:`text-right px-4 py-3 font-medium`},`归档数量`),c(`th`,{class:`text-left px-4 py-3 font-medium`},`最新归档`),c(`th`,{class:`text-right px-4 py-3 font-medium`},`部署目录`),c(`th`,{class:`text-right px-6 py-3 font-medium`},`操作`)])],-1),c(`tbody`,null,[(e(!0),u(o,null,i(F.value,t=>(e(),u(`tr`,{key:t.projectId,class:`border-b border-border last:border-0 hover:bg-base/40 transition-colors`},[c(`td`,Re,[c(`div`,ze,f(t.projectName),1),c(`div`,Be,f(t.projectId),1)]),c(`td`,Ve,f(K(t.artifactsBytes)),1),c(`td`,He,f(t.artifactCount),1),c(`td`,Ue,f(q(t.newestAt)),1),c(`td`,We,[t.deployPathExists?(e(),u(`div`,Ge,f(K(t.deployPathBytes)),1)):(e(),u(`div`,Ke,`未创建`)),t.deployPath?(e(),u(`div`,qe,f(t.deployPath),1)):d(``,!0)]),c(`td`,Je,[c(`button`,{onClick:e=>Z(t),class:`inline-flex items-center px-3 py-1.5 text-xs text-primary border border-primary/30 hover:bg-primary/10 rounded-md transition-colors`,type:`button`},[a[9]||=h(` 详情 `,-1),g(m(ie),{class:`w-3.5 h-3.5 ml-1`})],8,Ye)])]))),128))])])]))]),g(de,{name:`fade`},{default:t(()=>[R.value?(e(),u(`div`,{key:0,class:`fixed inset-0 z-40 flex`,onClick:ge(Q,[`self`])},[a[17]||=c(`div`,{class:`fixed inset-0 bg-black/50`},null,-1),c(`div`,Xe,[c(`div`,Ze,[c(`div`,null,[a[12]||=c(`div`,{class:`text-xs text-textMuted`},`归档详情`,-1),c(`h3`,Qe,f(z.value?.projectName),1)]),c(`button`,{onClick:Q,class:`text-textMuted hover:text-textMain p-2 rounded-md`,type:`button`},[g(m(me),{class:`w-5 h-5`})])]),c(`div`,$e,[V.value?(e(),u(`div`,M,`加载中...`)):H.value?(e(),u(`div`,et,f(H.value),1)):B.value?(e(),u(`div`,tt,[c(`div`,nt,[a[13]||=c(`div`,{class:`text-xs text-textMuted`},`归档总占用`,-1),c(`div`,rt,f(K(B.value.totalBytes))+` · `+f(B.value.items.length)+` 份`,1)]),B.value.items.length===0?(e(),u(`div`,it,`该项目暂无归档`)):(e(),u(`ul`,at,[(e(!0),u(o,null,i(B.value.items,t=>(e(),u(`li`,{key:t.deployId,class:`bg-base border border-border rounded-md px-4 py-3`},[c(`div`,ot,[c(`div`,st,[c(`div`,ct,[c(`span`,lt,f(t.deployId.slice(0,12)),1),c(`span`,{class:l([`px-1.5 py-0.5 text-[10px] font-mono rounded border`,$(t).cls])},f($(t).label),3),t.referencedBy>1?(e(),u(`span`,ut,` ref ×`+f(t.referencedBy),1)):d(``,!0)]),c(`div`,dt,[c(`span`,ft,f(K(t.sizeBytes)),1),a[14]||=c(`span`,null,`·`,-1),c(`span`,null,f(q(t.createdAt)),1)])]),c(`div`,pt,[t.canDelete?(e(),u(`button`,{key:0,onClick:e=>vt(t),class:`inline-flex items-center px-2.5 py-1.5 text-xs text-danger border border-danger/30 hover:bg-danger/10 rounded-md transition-colors`,type:`button`},[g(m(ue),{class:`w-3.5 h-3.5 mr-1`}),a[15]||=h(` 删除 `,-1)],8,mt)):(e(),u(`span`,{key:1,class:`inline-flex items-center px-2.5 py-1.5 text-xs text-textMuted italic`,title:`被 ${t.referencedBy} 条部署记录引用,不可单独删除`},[g(m(he),{class:`w-3.5 h-3.5 mr-1`}),a[16]||=h(` 受引用保护 `,-1)],8,ht))])])]))),128))]))])):d(``,!0)])])])):d(``,!0)]),_:1}),g(_e,{open:U.value,"onUpdate:open":a[0]||=e=>U.value=e,tone:`danger`,title:`删除归档 zip`,message:xt.value,"confirm-text":`确认删除`,"cancel-text":`取消`,loading:G.value,onConfirm:yt,onCancel:bt},null,8,[`open`,`message`,`loading`])]))}}),[[`__scopeId`,`data-v-3b5038e3`]]);export{N as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.fade-enter-active[data-v-3b5038e3],.fade-leave-active[data-v-3b5038e3]{transition:opacity .18s}.fade-enter-from[data-v-3b5038e3],.fade-leave-to[data-v-3b5038e3]{opacity:0}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility,.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}
|