e3efbd4552
Cron matching, audit/alert date filters, and schedule UI align on Asia/Shanghai while JWT/TOTP/heartbeat stay UTC; follow-ups add WS alert timestamps, fixed install timezone copy, and 422 on invalid date filters. Co-authored-by: Cursor <cursoragent@cursor.com>
4 lines
14 KiB
JavaScript
4 lines
14 KiB
JavaScript
import{a as e}from"./VDataTable-DNMnCp-Y.js";import{n as t,t as n}from"./useSnackbar-BN7WL7jT.js";import{n as r,t as i}from"./VRow-DQLoaeks.js";import{$ as a,At as o,Bt as ee,Cr as s,Dt as c,Et as te,Fr as l,Ft as ne,Hr as u,It as re,Lr as d,Lt as ie,N as ae,Nr as oe,Ot as se,P as f,Pr as ce,Pt as le,Rt as ue,Sr as p,Ut as de,Vt as fe,Wr as m,Y as pe,Zr as h,Zt as g,_ as me,_r as _,ai as v,bt as he,dr as ge,fr as y,gr as b,hr as x,jt as _e,kr as ve,nn as ye,ri as S,si as C,tn as be,v as xe,vr as w,xr as T,y as E,yr as D,zt as Se}from"./index-mgwiCK5j.js";import{n as Ce}from"./dataTable-esDY4cOk.js";import{t as we}from"./paginatedFetch-D86MsoFz.js";import{n as Te,t as O}from"./VCard-B9mXbrEC.js";import{t as Ee}from"./VSelect-7ey6zQ_i.js";import{t as De}from"./VDataTableServer-CKraLARR.js";import{t as k}from"./apiError-GQk-OOej.js";import{t as Oe}from"./useServerList-DRObYN-B.js";import{t as A}from"./_plugin-vue_export-helper-BDNMzG2s.js";import{n as ke,t as Ae}from"./execDetailGrouping-DrGynVlp.js";import{i as je,n as Me,r as Ne,t as Pe}from"./VExpansionPanels-DgHnOVf9.js";var Fe={class:`d-flex align-center flex-wrap ga-2 mb-4`},Ie={class:`text-h6`},Le={class:`text-caption text-medium-emphasis mb-2`},Re={key:0,class:`text-body-2 mb-3 pa-3 rounded bg-surface-variant overflow-auto`,style:{"max-height":`100px`}},ze={key:2,class:`d-flex flex-wrap ga-2 mb-3`},Be={class:`text-body-2`},Ve={class:`d-flex align-center flex-wrap ga-2 mb-3`},He=[`onClick`],Ue={class:`font-weight-medium`},We={key:0,class:`text-caption text-medium-emphasis`},Ge=[`title`],Ke={key:0},qe={class:`d-flex align-center ga-2 flex-grow-1 min-width-0`},Je=[`title`],Ye={key:0,class:`text-medium-emphasis`},Xe={class:`d-flex align-center flex-wrap ga-2 mb-4`},Ze={class:`text-caption text-medium-emphasis`},j=A(s({name:`ScriptRunsPage`,__name:`ScriptRunsPage`,setup(s){let A=be(),j=ye(),M=n(),{servers:Qe,loadServers:$e}=Oe(),N=x(()=>{let e=A.params.id;if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}),P=x(()=>se(A.query.kind)),et=x(()=>`${P.value===`server_batch`?`服务器任务`:`脚本执行`} #${N.value??``}`),F=h(!1),I=h([]),L=h(0),R=h(1),z=h(20),B=h(null),V=h(null),tt=[{title:`执行中`,value:`running`},{title:`已完成`,value:`completed`},{title:`部分成功`,value:`partial`},{title:`失败`,value:`failed`},{title:`已取消`,value:`cancelled`}],nt=[{title:`脚本`,value:`script`},{title:`服务器`,value:`server_batch`}],rt=Ce([{title:`ID`,key:`id`,width:72},{title:`类型`,key:`kind`,width:88},{title:`任务`,key:`label`},{title:`状态`,key:`status`,width:100},{title:`进度`,key:`progress`,width:88},{title:`台数`,key:`server_count`,width:72},{title:`操作人`,key:`operator`,width:88},{title:`开始时间`,key:`started_at`,width:168},{title:`操作`,key:`actions`,width:88}]),H=h(null),U=h(!1),W=h(`all`),G=h(`list`),it=h(null),at=h([]),K=null,ot=x(()=>new Map(Qe.value.map(e=>[e.id,e])));function st(e){return e||`—`}function ct(e){if(!e)return 0;try{let t=JSON.parse(e);return Array.isArray(t)?t.length:0}catch{return 0}}function lt(e){if(e.label)return e.label;let t=(e.command||``).replace(/^\[long_task\] /,``);return t.length>48?t.slice(0,48)+`…`:t||`执行 #${e.id}`}function ut(e){let t=(e.stderr||``).trim(),n=(e.stdout||``).trim(),r=(e.message||``).trim(),i=t||n||r||`—`;return{summary:(t||r||n||``).slice(0,200)||`—`,full:i}}let q=x(()=>{if(!H.value?.results)return[];let e=ot.value;return Object.entries(H.value.results).filter(([e])=>e!==`_meta`&&/^\d+$/.test(e)).map(([t,n])=>{let r=Number(t),i=e.get(r),a=String(n.status||``),o=n.phase?String(n.phase):void 0,s=n.exit_code??null,c=ut(n);return{serverId:t,serverIdNum:r,serverName:ee(t,H.value?.server_names,i?.name),serverDomain:i?.domain||``,status:a,phase:o,exitCode:s,summary:c.summary,fullOutput:c.full,failed:ue(a,o,s),pending:Se(o)}})}),dt=x(()=>W.value===`failed`?q.value.filter(e=>e.failed):W.value===`success`?q.value.filter(e=>!e.failed&&!e.pending):q.value),J=x(()=>fe(H.value?.results,H.value?.server_ids)),Y=x(()=>q.value.filter(e=>e.failed).map(e=>e.serverName)),X=x(()=>Ae(q.value.filter(e=>e.failed)));async function Z(e=!1){e||(F.value=!0);try{let e=await we(async(e,t)=>{let n={limit:e,offset:t};B.value&&(n.status=B.value),V.value&&(n.kind=V.value);let r=await g.get(`/execution-records`,n);return{items:r.items||[],total:r.total||0}},R.value,z.value);I.value=e.items,L.value=e.total}catch(t){e||(I.value=[],L.value=0,M(k(t,`加载失败`),`error`))}finally{e||(F.value=!1)}}function ft(e){R.value=e,Z()}function pt(e){z.value=e,R.value=1,Z()}function mt(e){j.push(c(e.id,e.kind))}async function Q(e=!1,t=!1){if(N.value){t||(U.value=!0);try{let t=new URLSearchParams({kind:P.value});e&&P.value===`script`&&t.set(`fetch_logs`,`true`),H.value=await g.get(`/execution-records/${N.value}?${t.toString()}`),H.value?.status===`running`?ht():$()}catch(e){t||M(k(e,`加载详情失败`),`error`)}finally{t||(U.value=!1)}}}function ht(){K||=setInterval(()=>{Q(!1,!0)},3e3)}function $(){K&&=(clearInterval(K),null)}function gt(e){it.value=it.value===e?null:e}function _t(e){j.push({path:`/terminal`,query:{server_id:String(e)}})}async function vt(){if(N.value)try{await g.post(`/scripts/executions/${N.value}/stop`),await Q(!1),M(`已发送停止指令`)}catch(e){M(k(e,`停止失败`),`error`)}}async function yt(){if(N.value)try{let e=await g.post(`/scripts/executions/${N.value}/retry`,{}),t=ct(e.server_ids);_e(e.id,`${lt(e)}(重试)`,t,!!e.long_task,e.progress,e.status),he(`重试已提交 #${e.id}`),j.push(c(e.id,`script`))}catch(e){M(k(e,`重试失败`),`error`)}}function bt(e){let t=e.serverDomain?` (${e.serverDomain})`:``,n=e.exitCode==null?``:` · exit ${e.exitCode}`,r=e.summary.split(`
|
||
`)[0]?.trim()||e.summary,i=r&&r!==`—`?` · ${r.slice(0,120)}`:``;return`- ${e.serverName}${t}${n}${i}`}async function xt(e,t){try{await navigator.clipboard.writeText(e),M(t)}catch{M(`复制失败`,`error`)}}async function St(){let e=q.value.filter(e=>e.failed);e.length&&await xt([`执行 #${N.value} · 失败 ${e.length} 台`,...e.map(bt)].join(`
|
||
`),`已复制失败清单`)}async function Ct(){let e=X.value;if(!e.length)return;let t=[`执行 #${N.value} · 失败分组 ${e.length} 类`];for(let n of e){t.push(`\n[${n.count} 台] ${n.errorKey}`);for(let e of n.rows.slice(0,20))t.push(` - ${e.serverName}`);n.rows.length>20&&t.push(` …及其他 ${n.rows.length-20} 台`)}await xt(t.join(`
|
||
`),`已复制分组摘要`)}u(B,()=>{R.value=1,Z()}),u(V,()=>{R.value=1,Z()}),u([N,P],([e])=>{$(),H.value=null,e?(W.value=`all`,G.value=`list`,Q(!1)):Z()},{immediate:!0}),ke(e=>Z(e),{enabled:()=>!N.value});let wt=o(()=>{N.value?Q(!1,!0):Z(!0)}),Tt=!1;return oe(async()=>{await $e({all:!0}),Tt=!0}),ve(async()=>{Tt&&(await $e({all:!0}),N.value?await Q(!1,!0):await Z(!0))}),ce(()=>{$(),wt()}),(n,o)=>(l(),_(t,{fluid:``,class:`pa-4`},{default:m(()=>[N.value?(l(),D(y,{key:0},[b(`div`,Fe,[p(f,{variant:`text`,"prepend-icon":`mdi-arrow-left`,onClick:o[0]||=e=>S(j).push(`/executions`)},{default:m(()=>[...o[8]||=[T(` 返回列表 `,-1)]]),_:1}),b(`h1`,Ie,C(et.value),1),H.value?(l(),_(E,{key:0,color:S(re)(H.value.status),size:`small`,variant:`tonal`,label:``},{default:m(()=>[T(C(S(ie)(H.value.status)),1)]),_:1},8,[`color`])):w(``,!0),p(me),H.value?.long_task&&P.value===`script`?(l(),_(f,{key:1,size:`small`,variant:`tonal`,loading:U.value,onClick:o[1]||=e=>Q(!0)},{default:m(()=>[...o[9]||=[T(` 拉取日志 `,-1)]]),_:1},8,[`loading`])):w(``,!0),P.value===`script`&&H.value&&(H.value.status===`running`||H.value.status===`partial`)?(l(),_(f,{key:2,size:`small`,variant:`text`,color:`error`,onClick:vt},{default:m(()=>[...o[10]||=[T(` 停止 `,-1)]]),_:1})):w(``,!0),P.value===`script`&&H.value&&(H.value.status===`failed`||H.value.status===`partial`)?(l(),_(f,{key:3,size:`small`,variant:`tonal`,color:`primary`,onClick:yt},{default:m(()=>[...o[11]||=[T(` 重试失败项 `,-1)]]),_:1})):w(``,!0)]),U.value&&!H.value?(l(),_(O,{key:0,elevation:`0`,border:``,rounded:`lg`,class:`pa-8 text-center`},{default:m(()=>[p(pe,{indeterminate:``,color:`primary`})]),_:1})):H.value?(l(),_(O,{key:1,elevation:`0`,border:``,rounded:`lg`},{default:m(()=>[p(Te,null,{default:m(()=>[b(`div`,Le,C(st(H.value.progress))+` · 操作人 `+C(H.value.operator||`—`),1),P.value===`script`?(l(),D(`pre`,Re,C(H.value.command),1)):(l(),_(E,{key:1,size:`small`,variant:`tonal`,color:`info`,class:`mb-3`,label:``},{default:m(()=>[T(C(S(te)(P.value))+` · `+C(H.value.label||H.value.op||`—`),1)]),_:1})),J.value.total?(l(),D(`div`,ze,[p(E,{size:`small`,variant:`tonal`,label:``},{default:m(()=>[T(`共 `+C(J.value.total)+` 台`,1)]),_:1}),J.value.success?(l(),_(E,{key:0,color:`success`,size:`small`,variant:`tonal`,label:``},{default:m(()=>[T(` 成功 `+C(J.value.success),1)]),_:1})):w(``,!0),J.value.failed?(l(),_(E,{key:1,color:`error`,size:`small`,variant:`tonal`,label:``},{default:m(()=>[T(` 失败 `+C(J.value.failed),1)]),_:1})):w(``,!0),J.value.pending?(l(),_(E,{key:2,color:`info`,size:`small`,variant:`tonal`,label:``},{default:m(()=>[T(` 进行中 `+C(J.value.pending),1)]),_:1})):w(``,!0)])):w(``,!0),Y.value.length?(l(),_(ae,{key:3,type:`error`,variant:`tonal`,density:`compact`,class:`mb-3`,title:`失败 ${Y.value.length} 台`},{default:m(()=>[b(`div`,Be,C(Y.value.join(`、`)),1)]),_:1},8,[`title`])):w(``,!0),b(`div`,Ve,[o[20]||=b(`span`,{class:`text-caption text-medium-emphasis`},`筛选`,-1),p(a,{modelValue:W.value,"onUpdate:modelValue":o[2]||=e=>W.value=e,mandatory:``,density:`compact`,color:`primary`,variant:`outlined`,divided:``},{default:m(()=>[p(f,{value:`all`,size:`small`},{default:m(()=>[...o[12]||=[T(`全部`,-1)]]),_:1}),p(f,{value:`failed`,size:`small`},{default:m(()=>[...o[13]||=[T(`仅失败`,-1)]]),_:1}),p(f,{value:`success`,size:`small`},{default:m(()=>[...o[14]||=[T(`仅成功`,-1)]]),_:1})]),_:1},8,[`modelValue`]),J.value.failed>0?(l(),D(y,{key:0},[p(xe,{vertical:``,class:`mx-1`}),o[19]||=b(`span`,{class:`text-caption text-medium-emphasis`},`视图`,-1),p(a,{modelValue:G.value,"onUpdate:modelValue":o[3]||=e=>G.value=e,mandatory:``,density:`compact`,color:`primary`,variant:`outlined`,divided:``},{default:m(()=>[p(f,{value:`list`,size:`small`},{default:m(()=>[...o[15]||=[T(`列表`,-1)]]),_:1}),p(f,{value:`group`,size:`small`},{default:m(()=>[...o[16]||=[T(`按错误分组`,-1)]]),_:1})]),_:1},8,[`modelValue`]),p(f,{size:`small`,variant:`tonal`,"prepend-icon":`mdi-content-copy`,onClick:St},{default:m(()=>[...o[17]||=[T(` 复制失败清单 `,-1)]]),_:1}),G.value===`group`?(l(),_(f,{key:0,size:`small`,variant:`tonal`,"prepend-icon":`mdi-content-copy`,onClick:Ct},{default:m(()=>[...o[18]||=[T(` 复制分组摘要 `,-1)]]),_:1})):w(``,!0)],64)):w(``,!0)]),G.value===`list`?(l(),_(e,{key:4,density:`compact`},{default:m(()=>[o[22]||=b(`thead`,null,[b(`tr`,null,[b(`th`,null,`服务器`),b(`th`,null,`状态`),b(`th`,{style:{width:`72px`}},`退出码`),b(`th`,null,`错误摘要`),b(`th`,{style:{width:`120px`},class:`text-end`},`操作`)])],-1),b(`tbody`,null,[(l(!0),D(y,null,d(dt.value,e=>(l(),D(`tr`,{key:e.serverId,class:v([{"exec-detail-row--failed":e.failed},`cursor-pointer`]),onClick:t=>gt(e.serverId)},[b(`td`,null,[b(`div`,Ue,C(e.serverName),1),e.serverDomain?(l(),D(`div`,We,C(e.serverDomain),1)):w(``,!0)]),b(`td`,null,[p(E,{color:S(le)(e.status,e.phase,e.exitCode),size:`x-small`,variant:`tonal`,label:``},{default:m(()=>[T(C(S(ne)(e.status,e.phase)),1)]),_:2},1032,[`color`])]),b(`td`,{class:v({"text-error font-weight-medium":e.failed})},C(e.exitCode??`—`),3),b(`td`,{class:`text-truncate`,style:{"max-width":`280px`},title:e.summary},C(e.summary),9,Ge),b(`td`,{class:`text-end`,onClick:o[4]||=ge(()=>{},[`stop`])},[p(f,{size:`x-small`,variant:`text`,icon:`mdi-console`,title:`打开终端`,onClick:t=>_t(e.serverIdNum)},null,8,[`onClick`])])],10,He))),128)),dt.value.length===0?(l(),D(`tr`,Ke,[...o[21]||=[b(`td`,{colspan:`5`,class:`text-center text-medium-emphasis py-4`},`当前筛选无记录`,-1)]])):w(``,!0)])]),_:1})):X.value.length?(l(),_(Pe,{key:5,modelValue:at.value,"onUpdate:modelValue":o[5]||=e=>at.value=e,multiple:``,variant:`accordion`},{default:m(()=>[(l(!0),D(y,null,d(X.value,(e,t)=>(l(),_(Me,{key:`${t}-${e.errorKey}`},{default:m(()=>[p(Ne,null,{default:m(()=>[b(`div`,qe,[b(`span`,{class:`text-body-2 text-truncate`,title:e.errorKey},C(e.errorKey),9,Je),p(E,{color:`error`,size:`x-small`,variant:`tonal`,label:``},{default:m(()=>[T(C(e.count)+` 台`,1)]),_:2},1024)])]),_:2},1024),p(je,null,{default:m(()=>[(l(!0),D(y,null,d(e.rows,e=>(l(),D(`div`,{key:e.serverId,class:`text-body-2 py-1`},[T(C(e.serverName)+` `,1),e.serverDomain?(l(),D(`span`,Ye,`(`+C(e.serverDomain)+`)`,1)):w(``,!0)]))),128))]),_:2},1024)]),_:2},1024))),128))]),_:1},8,[`modelValue`])):w(``,!0)]),_:1})]),_:1})):w(``,!0)],64)):(l(),D(y,{key:1},[b(`div`,Xe,[o[24]||=b(`h1`,{class:`text-h6`},`执行记录`,-1),p(me),p(f,{variant:`tonal`,"prepend-icon":`mdi-refresh`,loading:F.value,onClick:Z},{default:m(()=>[...o[23]||=[T(` 刷新 `,-1)]]),_:1},8,[`loading`])]),p(O,{elevation:`0`,border:``,rounded:`lg`},{default:m(()=>[p(Te,null,{default:m(()=>[p(i,{dense:``,class:`mb-2`},{default:m(()=>[p(r,{cols:`12`,sm:`4`},{default:m(()=>[p(Ee,{modelValue:V.value,"onUpdate:modelValue":o[6]||=e=>V.value=e,items:nt,label:`类型`,variant:`outlined`,density:`compact`,"hide-details":``,clearable:``},null,8,[`modelValue`])]),_:1}),p(r,{cols:`12`,sm:`4`},{default:m(()=>[p(Ee,{modelValue:B.value,"onUpdate:modelValue":o[7]||=e=>B.value=e,items:tt,label:`状态筛选`,variant:`outlined`,density:`compact`,"hide-details":``,clearable:``},null,8,[`modelValue`])]),_:1})]),_:1}),p(De,{headers:S(rt),items:I.value,"items-length":L.value,loading:F.value,"items-per-page":z.value,page:R.value,"onUpdate:page":ft,"onUpdate:itemsPerPage":pt},{"item.kind":m(({item:e})=>[p(E,{size:`x-small`,variant:`tonal`,label:``},{default:m(()=>[T(C(S(te)(e.kind)),1)]),_:2},1024)]),"item.label":m(({item:e})=>[T(C(e.label),1)]),"item.status":m(({item:e})=>[p(E,{color:S(re)(e.status),size:`x-small`,variant:`tonal`,label:``},{default:m(()=>[T(C(S(ie)(e.status)),1)]),_:2},1032,[`color`])]),"item.progress":m(({item:e})=>[T(C(st(e.progress)),1)]),"item.server_count":m(({item:e})=>[T(C(e.server_count),1)]),"item.started_at":m(({item:e})=>[b(`span`,Ze,C(S(de)(e.started_at)),1)]),"item.actions":m(({item:e})=>[p(f,{size:`x-small`,variant:`text`,color:`primary`,onClick:t=>mt(e)},{default:m(()=>[...o[25]||=[T(` 详情 `,-1)]]),_:1},8,[`onClick`])]),"no-data":m(()=>[...o[26]||=[b(`div`,{class:`text-center text-medium-emphasis py-6`},`暂无执行记录`,-1)]]),_:1},8,[`headers`,`items`,`items-length`,`loading`,`items-per-page`,`page`])]),_:1})]),_:1})],64))]),_:1}))}}),[[`__scopeId`,`data-v-aa0343c7`]]);export{j as default}; |