@wanghaopeng1148/deskpet 2.0.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/README.md +394 -0
- package/bin/deskpet.mjs +142 -0
- package/dist/web/assets/DashboardView-BLXa7VrZ.css +1 -0
- package/dist/web/assets/DashboardView-CTyWcLtQ.js +60 -0
- package/dist/web/assets/SettingsView-7c3RiRrt.js +1 -0
- package/dist/web/assets/SettingsView-BkL0OpZC.css +1 -0
- package/dist/web/assets/TasksView-BTK1OTwU.css +1 -0
- package/dist/web/assets/TasksView-s1MaR5sZ.js +5 -0
- package/dist/web/assets/ToolsView-B8V-A1j_.js +178 -0
- package/dist/web/assets/ToolsView-DGLJATQ9.css +1 -0
- package/dist/web/assets/WeChatView-ChLBhPso.js +1 -0
- package/dist/web/assets/WeChatView-CvdhJ05E.css +1 -0
- package/dist/web/assets/browser-CjSdxGTc.js +8 -0
- package/dist/web/assets/dashboard-DJ_Miuzx.js +93 -0
- package/dist/web/assets/dashboard-Fbcagzwx.css +1 -0
- package/dist/web/dashboard/index.html +13 -0
- package/package.json +71 -0
- package/resources/icons/tray.png +0 -0
- package/resources/icons/tray@2x.png +0 -0
- package/resources/previews/busy.png +0 -0
- package/resources/previews/click.png +0 -0
- package/resources/previews/hover.png +0 -0
- package/resources/previews/idle.png +0 -0
- package/resources/previews/preview.png +0 -0
- package/resources/previews/sleep.png +0 -0
- package/resources/skins/default_cute/pet.json +7 -0
- package/resources/skins/default_cute/spritesheet.webp +0 -0
- package/resources/skins/default_cute/submission.json +29 -0
- package/server/db/database.ts +118 -0
- package/server/db/migrate-legacy.ts +121 -0
- package/server/db/task-repository.ts +585 -0
- package/server/http/http-server.ts +725 -0
- package/server/http/ws-hub.ts +66 -0
- package/server/main.ts +322 -0
- package/server/plugins/actions/builtin.ts +73 -0
- package/server/plugins/actions/clipboard-watch.ts +38 -0
- package/server/plugins/actions/http-request.ts +53 -0
- package/server/plugins/actions/jenkins-build.ts +209 -0
- package/server/plugins/actions/open-app.ts +40 -0
- package/server/plugins/actions/python-script.ts +187 -0
- package/server/plugins/actions/screenshot.ts +41 -0
- package/server/plugins/actions/send-keystroke.ts +103 -0
- package/server/plugins/actions/show-reminder.ts +16 -0
- package/server/plugins/actions/ssh-command.ts +148 -0
- package/server/plugins/actions/task-chain.ts +30 -0
- package/server/plugins/actions/volume-control.ts +35 -0
- package/server/plugins/index.ts +37 -0
- package/server/plugins/registry.ts +72 -0
- package/server/services/clipboard-watcher.ts +126 -0
- package/server/services/config-store.ts +152 -0
- package/server/services/idle-monitor.ts +146 -0
- package/server/services/notifier.ts +54 -0
- package/server/services/quick-actions-store.ts +54 -0
- package/server/services/remote-connector.ts +75 -0
- package/server/services/scanner-reader.ts +257 -0
- package/server/services/script-runner.ts +263 -0
- package/server/services/snapshot-service.ts +196 -0
- package/server/services/task-scheduler.ts +900 -0
- package/server/services/wechat-bot.ts +744 -0
- package/server/services/wechat-command-types.ts +15 -0
- package/server/services/wechat-commands.ts +367 -0
- package/server/suppress-warnings.ts +10 -0
- package/server/utils/asset-url.ts +27 -0
- package/server/utils/auto-start.ts +90 -0
- package/server/utils/clipboard.ts +50 -0
- package/server/utils/dashboard-url.ts +9 -0
- package/server/utils/instance-guard.ts +170 -0
- package/server/utils/native-notify.ts +68 -0
- package/server/utils/open.ts +38 -0
- package/server/utils/paths.ts +72 -0
- package/server/utils/python-interpreter.ts +154 -0
- package/shared/animation-engine.ts +422 -0
- package/shared/chain-condition.ts +60 -0
- package/shared/cron-weekly.ts +131 -0
- package/shared/py-task-params.ts +356 -0
- package/shared/types.ts +309 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as fe,o as ye,c as m,e as k,g as i,m as X,w as a,f as M,h as l,r as d,j as r,k as p,i as s,t as g,F as R,l as N,n as Y,E as w,z as ke,_ as we}from"./dashboard-DJ_Miuzx.js";const Ve={class:"page"},ge={key:0,style:{color:"#f56c6c","font-size":"13px"}},ce={key:1,style:{"font-size":"13px",color:"#909399"}},be={key:2,style:{"font-size":"13px",color:"#c0c4cc"}},_e={class:"hint"},xe={class:"srv-list"},Se={class:"srv-row"},Ce={class:"srv-row"},Ue={style:{"margin-top":"12px","text-align":"right"}},ze={class:"card-head"},je={class:"btn-gap"},Te=fe({__name:"SettingsView",setup(he){const n=d(null),T=d(!1),z=d([]),c=d(!1),S=d(!1),h=d(""),j=d(null),$=d(null),B=d([]),F=d(!1);async function O(){n.value=await r.getSettings();try{z.value=await r.snapshots(),await L(),await J()}catch{}}async function L(){try{const o=await r.scannerPorts();B.value=o.ports}catch{}}async function J(){var o;try{const e=await r.scannerStatus();c.value=e.running,S.value=e.connected,h.value=((o=e.settings)==null?void 0:o.port)??"",j.value=e.error,$.value=e.lastStatus}catch{}}async function Z(){F.value=!0;try{if(c.value)await r.scannerStop(),S.value=!1,c.value=!1;else{const o=await r.scannerStart();if(await J(),!o.ok||!S.value){const e=j.value||o.error||"请检查串口配置与占用情况";w.error(`连接失败:${e}`)}else w.success("扫码枪已连接")}}catch(o){w.error(`操作失败: ${String(o)}`)}finally{F.value=!1}}async function ee(){if(n.value){T.value=!0;try{const o=await r.saveSettings(n.value);n.value=o.settings,w.success("设置已保存(部分项需重启应用生效)")}catch(o){w.error(`保存失败: ${String(o)}`)}finally{T.value=!1}}}const D=d(null),b=d({}),I=d(!1),C=d(null);function le(){n.value&&n.value.servers.push({id:`srv_${Date.now().toString(36)}`,name:`服务器 ${n.value.servers.length+1}`,host:"",port:22,username:"root",password:""})}function te(o){var e;(e=n.value)==null||e.servers.splice(o,1)}async function ae(o){D.value=o.id;try{const e=await r.testServer({host:o.host,port:o.port,username:o.username,password:o.password});b.value={...b.value,[o.id]:e}}catch(e){b.value={...b.value,[o.id]:{ok:!1,message:String(e)}}}finally{D.value=null}}async function ne(){if(n.value){I.value=!0;try{C.value=await r.testJenkins({url:n.value.jenkins.url,username:n.value.jenkins.username,password:n.value.jenkins.password})}catch(o){C.value={ok:!1,message:String(o)}}finally{I.value=!1}}}const P=d(!1);async function oe(){P.value=!0;try{const o=await r.createSnapshot();w.success(`快照 #${o.id} 已创建`),z.value=await r.snapshots()}finally{P.value=!1}}async function se(o){await ke.confirm(`确定恢复到快照 #${o}?当前配置会先自动备份。`,"恢复确认",{type:"warning",confirmButtonText:"恢复",cancelButtonText:"取消"}),(await r.restoreSnapshot(o)).ok?w.success("已恢复"):w.error("恢复失败")}async function ue(o){await r.deleteSnapshot(o),z.value=await r.snapshots()}function ie(){location.href=r.exportUrl()}const W=d(null);function de(){var o;(o=W.value)==null||o.click()}async function re(o){var V;const e=o.target,_=(V=e.files)==null?void 0:V[0];if(!_)return;const u=await _.text(),y=await r.importPack(u);y.ok?w.success(y.message):w.error(y.message),e.value="",y.ok&&await O()}return ye(()=>void O()),(o,e)=>{const _=p("el-input-number"),u=p("el-form-item"),y=p("el-switch"),V=p("el-divider"),A=p("el-radio-button"),pe=p("el-radio-group"),H=p("el-tag"),v=p("el-button"),q=p("el-option"),G=p("el-select"),K=p("el-checkbox"),x=p("el-input"),me=p("el-form"),Q=p("el-card"),U=p("el-table-column"),ve=p("el-table");return m(),k("div",Ve,[e[47]||(e[47]=i("div",{class:"page-title"},"系统设置",-1)),n.value?(m(),X(Q,{key:0,shadow:"never",style:{"max-width":"640px"}},{default:a(()=>[l(me,{"label-width":"110px"},{default:a(()=>[l(u,{label:"闲置休眠"},{default:a(()=>[l(_,{modelValue:n.value.system.idleSleepMinutes,"onUpdate:modelValue":e[0]||(e[0]=t=>n.value.system.idleSleepMinutes=t),min:1,max:60},null,8,["modelValue"]),e[17]||(e[17]=i("span",{class:"hint"},"分钟无交互后进入休眠",-1))]),_:1}),l(u,{label:"开机自启"},{default:a(()=>[l(y,{modelValue:n.value.system.autoStart,"onUpdate:modelValue":e[1]||(e[1]=t=>n.value.system.autoStart=t)},null,8,["modelValue"]),e[18]||(e[18]=i("span",{class:"hint"},"登录系统后自动启动 DeskPet",-1))]),_:1}),l(V,{"content-position":"left"},{default:a(()=>[...e[19]||(e[19]=[s("任务可靠性",-1)])]),_:1}),l(u,{label:"失败熔断阈值"},{default:a(()=>[l(_,{modelValue:n.value.tasks.breakerThreshold,"onUpdate:modelValue":e[2]||(e[2]=t=>n.value.tasks.breakerThreshold=t),min:0,max:20},null,8,["modelValue"]),e[20]||(e[20]=i("span",{class:"hint"},"连续失败达到该次数自动禁用任务并告警;0 = 关闭熔断",-1))]),_:1}),l(V,{"content-position":"left"},{default:a(()=>[...e[21]||(e[21]=[s("管理台服务 (WebUI)",-1)])]),_:1}),l(u,{label:"监听地址"},{default:a(()=>[l(pe,{modelValue:n.value.server.host,"onUpdate:modelValue":e[3]||(e[3]=t=>n.value.server.host=t)},{default:a(()=>[l(A,{value:"127.0.0.1"},{default:a(()=>[...e[22]||(e[22]=[s("仅本机",-1)])]),_:1}),l(A,{value:"0.0.0.0"},{default:a(()=>[...e[23]||(e[23]=[s("局域网开放",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),l(u,{label:"端口"},{default:a(()=>[l(_,{modelValue:n.value.server.port,"onUpdate:modelValue":e[4]||(e[4]=t=>n.value.server.port=t),min:1024,max:65535},null,8,["modelValue"]),e[24]||(e[24]=i("span",{class:"hint"},"默认 3210,修改后需重启",-1))]),_:1}),l(V,{"content-position":"left"},{default:a(()=>[...e[25]||(e[25]=[s("微信 Bot",-1)])]),_:1}),l(u,{label:"任务完成推送"},{default:a(()=>[l(y,{modelValue:n.value.wechat.notifyOnTaskComplete,"onUpdate:modelValue":e[5]||(e[5]=t=>n.value.wechat.notifyOnTaskComplete=t)},null,8,["modelValue"])]),_:1}),l(u,{label:"任务失败推送"},{default:a(()=>[l(y,{modelValue:n.value.wechat.notifyOnTaskFailed,"onUpdate:modelValue":e[6]||(e[6]=t=>n.value.wechat.notifyOnTaskFailed=t)},null,8,["modelValue"])]),_:1}),l(u,{label:"远程指令"},{default:a(()=>[l(y,{modelValue:n.value.wechat.allowRemoteCommand,"onUpdate:modelValue":e[7]||(e[7]=t=>n.value.wechat.allowRemoteCommand=t)},null,8,["modelValue"]),e[26]||(e[26]=i("span",{class:"hint"},"允许通过微信文字指令操控桌宠",-1))]),_:1}),l(V,{"content-position":"left"},{default:a(()=>[...e[27]||(e[27]=[s("扫码枪(串口)",-1)])]),_:1}),l(u,{label:"运行状态"},{default:a(()=>[l(H,{type:S.value?"success":c.value?"warning":"info",size:"small"},{default:a(()=>[s(g(S.value?"已连接"+(h.value?" · "+h.value:""):c.value?"连接中…":"未连接"),1)]),_:1},8,["type"]),l(v,{size:"small",style:{"margin-left":"12px"},type:c.value?"danger":"primary",loading:F.value,onClick:Z},{default:a(()=>[s(g(c.value?"断开":"连接"),1)]),_:1},8,["type","loading"]),e[28]||(e[28]=i("span",{class:"hint"},'手动控制当前连接(不影响"自动开启"设置)',-1))]),_:1}),l(u,{label:"连接诊断"},{default:a(()=>[j.value?(m(),k("span",ge,"⚠ "+g(j.value),1)):$.value?(m(),k("span",ce,g($.value.message),1)):(m(),k("span",be,"尚未连接"))]),_:1}),l(u,{label:"自动开启"},{default:a(()=>[l(y,{modelValue:n.value.scanner.enabled,"onUpdate:modelValue":e[8]||(e[8]=t=>n.value.scanner.enabled=t)},null,8,["modelValue"]),e[29]||(e[29]=i("span",{class:"hint"},"启动应用时自动连接扫码枪",-1))]),_:1}),l(u,{label:"串口"},{default:a(()=>[l(G,{modelValue:n.value.scanner.port,"onUpdate:modelValue":e[9]||(e[9]=t=>n.value.scanner.port=t),filterable:"","allow-create":"","default-first-option":"",placeholder:"选择或输入串口号,如 COM9",style:{width:"260px"},onVisibleChange:e[10]||(e[10]=t=>t&&L())},{default:a(()=>[(m(!0),k(R,null,N(B.value,t=>(m(),X(q,{key:t,label:t,value:t},null,8,["label","value"]))),128))]),_:1},8,["modelValue"]),i("span",_e,"检测到 "+g(B.value.length)+" 个串口",1)]),_:1}),l(u,{label:"波特率"},{default:a(()=>[l(G,{modelValue:n.value.scanner.baud,"onUpdate:modelValue":e[11]||(e[11]=t=>n.value.scanner.baud=t),style:{width:"140px"}},{default:a(()=>[(m(),k(R,null,N([4800,9600,19200,38400,57600,115200],t=>l(q,{key:t,label:String(t),value:t},null,8,["label","value"])),64))]),_:1},8,["modelValue"])]),_:1}),l(u,{label:"扫码通知"},{default:a(()=>[l(K,{modelValue:n.value.scanner.notifyWechat,"onUpdate:modelValue":e[12]||(e[12]=t=>n.value.scanner.notifyWechat=t)},{default:a(()=>[...e[30]||(e[30]=[s("微信推送",-1)])]),_:1},8,["modelValue"]),l(K,{modelValue:n.value.scanner.notifyDesktop,"onUpdate:modelValue":e[13]||(e[13]=t=>n.value.scanner.notifyDesktop=t)},{default:a(()=>[...e[31]||(e[31]=[s("桌面提醒",-1)])]),_:1},8,["modelValue"])]),_:1}),l(V,{"content-position":"left"},{default:a(()=>[...e[32]||(e[32]=[s("Linux 服务器(SSH)",-1)])]),_:1}),l(u,{label:"服务器列表","label-position":"top"},{default:a(()=>[i("div",xe,[(m(!0),k(R,null,N(n.value.servers,(t,E)=>(m(),k("div",{key:t.id,class:"srv-item"},[i("div",Se,[l(x,{modelValue:t.name,"onUpdate:modelValue":f=>t.name=f,placeholder:"名称",style:{width:"130px"}},null,8,["modelValue","onUpdate:modelValue"]),l(x,{modelValue:t.host,"onUpdate:modelValue":f=>t.host=f,placeholder:"IP / 主机名",style:{width:"180px"}},null,8,["modelValue","onUpdate:modelValue"]),l(_,{modelValue:t.port,"onUpdate:modelValue":f=>t.port=f,min:1,max:65535,"controls-position":"right",style:{width:"118px"}},null,8,["modelValue","onUpdate:modelValue"])]),i("div",Ce,[l(x,{modelValue:t.username,"onUpdate:modelValue":f=>t.username=f,placeholder:"用户名",style:{width:"130px"}},null,8,["modelValue","onUpdate:modelValue"]),l(x,{modelValue:t.password,"onUpdate:modelValue":f=>t.password=f,type:"password","show-password":"",placeholder:"密码",style:{width:"180px"}},null,8,["modelValue","onUpdate:modelValue"]),l(v,{size:"small",loading:D.value===t.id,onClick:f=>ae(t)},{default:a(()=>[...e[33]||(e[33]=[s(" 测试连接 ",-1)])]),_:1},8,["loading","onClick"]),l(v,{size:"small",type:"danger",link:"",onClick:f=>te(E)},{default:a(()=>[...e[34]||(e[34]=[s("删除",-1)])]),_:1},8,["onClick"])]),b.value[t.id]?(m(),k("div",{key:0,class:Y(["test-msg",b.value[t.id].ok?"ok":"bad"])},g(b.value[t.id].message),3)):M("",!0)]))),128)),l(v,{size:"small",onClick:le},{default:a(()=>[...e[35]||(e[35]=[s("+ 添加服务器",-1)])]),_:1}),e[36]||(e[36]=i("div",{class:"hint"}," 任务中可选这些服务器执行 Shell 命令;密码明文保存在本机 settings.json,请勿在共享环境使用 ",-1))])]),_:1}),l(V,{"content-position":"left"},{default:a(()=>[...e[37]||(e[37]=[s("Jenkins",-1)])]),_:1}),l(u,{label:"地址"},{default:a(()=>[l(x,{modelValue:n.value.jenkins.url,"onUpdate:modelValue":e[14]||(e[14]=t=>n.value.jenkins.url=t),placeholder:"http://jenkins.example.com:8080",style:{width:"320px"}},null,8,["modelValue"])]),_:1}),l(u,{label:"用户名"},{default:a(()=>[l(x,{modelValue:n.value.jenkins.username,"onUpdate:modelValue":e[15]||(e[15]=t=>n.value.jenkins.username=t),style:{width:"240px"}},null,8,["modelValue"])]),_:1}),l(u,{label:"密码/Token"},{default:a(()=>[l(x,{modelValue:n.value.jenkins.password,"onUpdate:modelValue":e[16]||(e[16]=t=>n.value.jenkins.password=t),type:"password","show-password":"",style:{width:"240px"}},null,8,["modelValue"])]),_:1}),l(u,{label:"连接测试"},{default:a(()=>[l(v,{size:"small",loading:I.value,onClick:ne},{default:a(()=>[...e[38]||(e[38]=[s("测试连接",-1)])]),_:1},8,["loading"]),C.value?(m(),k("span",{key:0,class:Y(["test-msg",C.value.ok?"ok":"bad"])},g(C.value.message),3)):M("",!0)]),_:1})]),_:1}),i("div",Ue,[l(v,{type:"primary",loading:T.value,onClick:ee},{default:a(()=>[...e[39]||(e[39]=[s("保存设置",-1)])]),_:1},8,["loading"])])]),_:1})):M("",!0),l(Q,{shadow:"never",style:{"max-width":"860px","margin-top":"16px"}},{header:a(()=>[i("div",ze,[e[43]||(e[43]=i("span",null,"备份与快照",-1)),i("div",je,[l(v,{size:"small",loading:P.value,onClick:oe},{default:a(()=>[...e[40]||(e[40]=[s("创建快照",-1)])]),_:1},8,["loading"]),l(v,{size:"small",onClick:ie},{default:a(()=>[...e[41]||(e[41]=[s("导出配置包",-1)])]),_:1}),l(v,{size:"small",onClick:de},{default:a(()=>[...e[42]||(e[42]=[s("导入配置包",-1)])]),_:1}),i("input",{ref_key:"importFileInput",ref:W,type:"file",accept:".deskpet,.json",hidden:"",onChange:re},null,544)])])]),default:a(()=>[l(ve,{data:z.value,size:"small",stripe:"","max-height":"260"},{empty:a(()=>[...e[46]||(e[46]=[s("暂无快照(配置变更时会自动创建,保留最近 20 份)",-1)])]),default:a(()=>[l(U,{prop:"id",label:"#",width:"60"}),l(U,{label:"时间",width:"180"},{default:a(({row:t})=>[s(g(new Date(t.createdAt).toLocaleString("zh-CN",{hour12:!1})),1)]),_:1}),l(U,{label:"类型",width:"90"},{default:a(({row:t})=>[l(H,{size:"small",type:t.reason==="auto"?"info":"primary"},{default:a(()=>[s(g(t.reason==="auto"?"自动":"手动"),1)]),_:2},1032,["type"])]),_:1}),l(U,{prop:"taskCount",label:"任务数",width:"80"}),l(U,{label:"操作",width:"140"},{default:a(({row:t})=>[l(v,{size:"small",type:"primary",link:"",onClick:E=>se(t.id)},{default:a(()=>[...e[44]||(e[44]=[s("恢复",-1)])]),_:1},8,["onClick"]),l(v,{size:"small",type:"danger",link:"",onClick:E=>ue(t.id)},{default:a(()=>[...e[45]||(e[45]=[s("删除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])]),_:1})])}}}),Be=we(Te,[["__scopeId","data-v-495190c5"]]);export{Be as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.hint[data-v-495190c5]{color:#a0a6b3;font-size:12px;margin-left:10px}.srv-list[data-v-495190c5]{width:100%}.srv-item[data-v-495190c5]{border:1px solid var(--dp-line);border-radius:10px;padding:10px 12px;margin-bottom:10px;background:#94aad40a}.srv-row[data-v-495190c5]{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.srv-row+.srv-row[data-v-495190c5]{margin-top:8px}.test-msg[data-v-495190c5]{font-size:12px;margin-top:6px}.test-msg.ok[data-v-495190c5]{color:#43e0aa}.test-msg.bad[data-v-495190c5]{color:#fb7185}.card-head[data-v-495190c5]{display:flex;justify-content:space-between;align-items:center}.btn-gap[data-v-495190c5]{display:flex;gap:8px;align-items:center}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.hint[data-v-137fad9b]{color:#a0a6b3;font-size:12px;margin-left:8px}.week-picker[data-v-137fad9b]{display:flex;flex-direction:column;gap:8px}.week-presets[data-v-137fad9b]{display:flex;gap:6px}.cron-summary[data-v-137fad9b]{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.cron-summary-text[data-v-137fad9b]{font-size:12.5px;color:var(--dp-text-2);background:#6c8cff1a;padding:3px 10px;border-radius:6px}.cron-manual-toggle[data-v-137fad9b]{margin-right:0}.cron-input[data-v-137fad9b]{margin-top:8px;font-family:SF Mono,Menlo,Consolas,monospace}.hint.block[data-v-137fad9b]{display:block;margin-left:0;margin-top:4px}.py-ip-list[data-v-137fad9b]{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:6px;font-size:12px}.py-ip-tip[data-v-137fad9b]{color:#a0a6b3}.py-ip-item[data-v-137fad9b]{padding:2px 8px;border-radius:6px;background:#6c8cff1a;color:#8fa8ff;font-family:SF Mono,Menlo,monospace;font-size:11.5px}.py-ip-none[data-v-137fad9b]{color:#fb7185}.py-import[data-v-137fad9b]{width:100%}.py-row[data-v-137fad9b]{display:flex;align-items:center;gap:10px;margin-bottom:8px}.py-name[data-v-137fad9b]{font-size:12px;color:#a0a6b3;font-family:SF Mono,Menlo,monospace}.py-param-tip[data-v-137fad9b]{margin-top:6px;font-size:12px;color:#8fa8ff}.py-code[data-v-137fad9b] textarea{font-family:SF Mono,Menlo,Consolas,monospace;font-size:12.5px;line-height:1.5;background:#0a0f1c80;color:#cfe0ff}.toolbar[data-v-37d8bb63]{display:flex;justify-content:space-between;align-items:center;gap:14px;margin-bottom:16px}.search[data-v-37d8bb63]{max-width:340px}.toolbar-right[data-v-37d8bb63]{display:flex;align-items:center;gap:12px}.queue-bar[data-v-37d8bb63]{border:1px solid var(--dp-line);border-radius:12px;padding:12px 16px;margin-bottom:16px;background:linear-gradient(120deg,#6c8cff0f,#9a6cff0a);transition:border-color .2s}.queue-bar.q-busy[data-v-37d8bb63]{border-color:#6c8cff73;box-shadow:0 0 0 1px #6c8cff1f}.queue-head[data-v-37d8bb63]{display:flex;align-items:center;gap:10px;margin-bottom:8px}.queue-actions[data-v-37d8bb63]{margin-left:auto;display:flex;gap:8px}.queue-title[data-v-37d8bb63]{font-size:13.5px;font-weight:700;display:inline-flex;align-items:center;gap:7px}.q-live[data-v-37d8bb63]{width:8px;height:8px;border-radius:50%;background:#5b6472}.q-live.on[data-v-37d8bb63]{background:#43e0aa;box-shadow:0 0 8px #34d399cc;animation:pulse-37d8bb63 1s ease-in-out infinite}.queue-sub[data-v-37d8bb63]{font-size:11.5px;color:var(--dp-text-3)}.queue-items[data-v-37d8bb63]{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.q-item[data-v-37d8bb63]{font-size:12.5px;padding:3px 10px;border-radius:999px;border:1px solid transparent;white-space:nowrap}.q-running[data-v-37d8bb63]{color:#8fa8ff;background:#6c8cff24;border-color:#6c8cff66}.q-wait[data-v-37d8bb63]{color:#fbbf24;background:#fbbf241a;border-color:#fbbf244d}.q-empty[data-v-37d8bb63]{font-size:12.5px;color:var(--dp-text-3)}.q-pos[data-v-37d8bb63]{margin-left:6px;font-size:11.5px;font-weight:700;color:#fbbf24}.table-card[data-v-37d8bb63]{overflow:hidden}.task-name[data-v-37d8bb63]{font-weight:600}.task-name.disabled[data-v-37d8bb63]{color:var(--dp-text-3);text-decoration:line-through;text-decoration-color:#94aad480}.ml6[data-v-37d8bb63]{margin-left:6px}.status-pill[data-v-37d8bb63]{display:inline-flex;align-items:center;gap:6px;font-size:12px;padding:3px 10px;border-radius:999px;border:1px solid transparent;white-space:nowrap}.status-dot[data-v-37d8bb63]{width:6px;height:6px;border-radius:50%;background:currentColor}.st-idle[data-v-37d8bb63],.st-cancelled[data-v-37d8bb63],.st-disabled[data-v-37d8bb63]{color:var(--dp-text-2);background:#94aad414;border-color:var(--dp-line-strong)}.st-pending[data-v-37d8bb63]{color:#fbbf24;background:#fbbf241a;border-color:#fbbf244d}.st-running[data-v-37d8bb63]{color:#8fa8ff;background:#6c8cff1f;border-color:#6c8cff59}.st-running .status-dot[data-v-37d8bb63]{animation:pulse-37d8bb63 1s ease-in-out infinite}.st-completed[data-v-37d8bb63]{color:#43e0aa;background:#34d3991a;border-color:#34d3994d}.st-failed[data-v-37d8bb63]{color:#fb7185;background:#fb71851a;border-color:#fb71854d}@keyframes pulse-37d8bb63{0%,to{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.75)}}.run-tip[data-v-37d8bb63]{font-size:12.5px;color:#8fa8ff;margin-bottom:14px}.run-help[data-v-37d8bb63]{font-size:12px;color:var(--dp-text-3);margin-top:4px;width:100%}.live-alert[data-v-37d8bb63]{margin-bottom:8px}.live-console[data-v-37d8bb63]{border:1px solid var(--dp-line);border-radius:10px;padding:10px 12px;margin-bottom:16px;background:#f7f8fb}.live-head[data-v-37d8bb63]{display:flex;align-items:center;gap:8px;margin-bottom:8px;font-size:12.5px}.live-title[data-v-37d8bb63]{font-weight:600;color:var(--dp-text-1)}.live-state[data-v-37d8bb63]{color:#8a90a0}.live-jump[data-v-37d8bb63]{margin-left:auto;color:#6c8cff;cursor:pointer;font-weight:600}.live-jump[data-v-37d8bb63]:hover{text-decoration:underline}.live-head .el-button[data-v-37d8bb63]{margin-left:auto}.live-jump+.el-button[data-v-37d8bb63]{margin-left:8px}.live-body[data-v-37d8bb63]{margin:0;max-height:320px;overflow:auto;padding:10px 12px;border-radius:8px;background:#1c2029;color:#d6dae3;font-family:SF Mono,Menlo,Consolas,monospace;font-size:11.5px;line-height:1.55;white-space:pre-wrap;word-break:break-all}.live-err[data-v-37d8bb63]{color:#ff8f8f;display:block}.live-empty[data-v-37d8bb63]{padding:14px;text-align:center;color:#98a0b0;font-size:12.5px;border-radius:8px;background:#eef0f5}.hist-head[data-v-37d8bb63]{display:flex;align-items:baseline;gap:8px;margin:4px 0 10px}.hist-title[data-v-37d8bb63]{font-weight:600;color:var(--dp-text-1);font-size:13px}.hist-hint[data-v-37d8bb63]{font-size:12px;color:#98a0b0}.log-head[data-v-37d8bb63]{display:flex;align-items:center;gap:10px;margin-bottom:4px}.log-duration[data-v-37d8bb63]{color:var(--dp-text-3);font-size:12px}.log-error[data-v-37d8bb63]{color:var(--dp-danger);font-size:13px;margin-bottom:4px;word-break:break-all}.log-detail summary[data-v-37d8bb63]{cursor:pointer;color:var(--dp-primary);font-size:13px}.log-detail pre[data-v-37d8bb63]{background:#0a0f1c99;border:1px solid var(--dp-line);padding:10px;border-radius:8px;font-size:12px;max-height:200px;overflow:auto;white-space:pre-wrap;word-break:break-all;margin-top:6px}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
var sl=Object.defineProperty;var il=(k,r,d)=>r in k?sl(k,r,{enumerable:!0,configurable:!0,writable:!0,value:d}):k[r]=d;var Ue=(k,r,d)=>il(k,typeof r!="symbol"?r+"":r,d);import{d as Ie,q as Ne,c as o,m as V,w as u,s as be,k as S,h as a,u as J,i as _,e as f,F as C,l as q,g as p,t as x,f as b,r as w,E as N,j as W,_ as Fe,o as rl,a as dl,b as ml,n as ce,v as cl,x as We,y as vl,z as ke}from"./dashboard-DJ_Miuzx.js";const ie={MANUAL:"manual",SCHEDULED:"scheduled",SCENE:"scene"},te={ONCE:"once",CRON:"cron",DELAY:"delay",INTERVAL:"interval"},he={IDLE:"idle",STARTUP:"startup",NETWORK:"network"};function pl(k){const r=/(^|\n)[ \t]*TASK_PARAMS\s*=\s*/.exec(k);if(!r)return null;const d=r.index+r[0].length,y=fl(k,d);return y===null?null:k.slice(d,y)}function fl(k,r){let d=r;for(;d<k.length&&/\s/.test(k[d]);)d++;const y=k[d];if(y!=="["&&y!=="{")return null;const h=[];let m=null;for(;d<k.length;d++){const t=k[d];if(m){if(t==="\\"){d++;continue}t===m&&(m=null);continue}if(t==="#"){for(;d<k.length&&k[d]!==`
|
|
2
|
+
`;)d++;continue}if(t==='"'||t==="'"){m=t;continue}if(t==="["||t==="{")h.push(t);else if((t==="]"||t==="}")&&(h.pop(),h.length===0))return d+1}return null}class yl{constructor(r){Ue(this,"i",0);Ue(this,"src");this.src=r}parse(){const r=this.value();if(this.skipWs(),this.i<this.src.length)throw new Error(`存在多余内容: ${this.src.slice(this.i,this.i+20)}`);return r}skipWs(){for(;;){for(;this.i<this.src.length&&/\s/.test(this.src[this.i]);)this.i++;if(this.src[this.i]==="#"){for(;this.i<this.src.length&&this.src[this.i]!==`
|
|
3
|
+
`;)this.i++;continue}break}}value(){this.skipWs();const r=this.src[this.i];if(r==="[")return this.list();if(r==="{")return this.dict();if(r==='"'||r==="'")return this.string();if(r&&/[A-Za-z_]/.test(r)){const d=this.ident(),y=this.src[this.i];if(y==='"'||y==="'"){if(d==="f"||d==="F")throw new Error("不支持 f-string");return this.string()}if(d==="True")return!0;if(d==="False")return!1;if(d==="None")return null;throw new Error(`不支持的标识符: ${d}`)}return this.number()}list(){const r=[];if(this.i++,this.skipWs(),this.src[this.i]==="]")return this.i++,r;for(;;){r.push(this.value()),this.skipWs();const d=this.src[this.i];if(d===","){if(this.i++,this.skipWs(),this.src[this.i]==="]"){this.i++;break}continue}if(d==="]"){this.i++;break}throw new Error("列表格式错误")}return r}dict(){const r={};if(this.i++,this.skipWs(),this.src[this.i]==="}")return this.i++,r;for(;;){this.skipWs();const d=this.value();if(this.skipWs(),this.src[this.i]!==":")throw new Error("字典缺少冒号");this.i++,r[String(d)]=this.value(),this.skipWs();const y=this.src[this.i];if(y===","){if(this.i++,this.skipWs(),this.src[this.i]==="}"){this.i++;break}continue}if(y==="}"){this.i++;break}throw new Error("字典格式错误")}return r}string(){const r=this.src[this.i];this.i++;let d="";for(;this.i<this.src.length;){const y=this.src[this.i];if(y==="\\"){const h=this.src[this.i+1];switch(this.i+=2,h){case"n":d+=`
|
|
4
|
+
`;break;case"t":d+=" ";break;case"r":d+="\r";break;case"\\":d+="\\";break;case"'":d+="'";break;case'"':d+='"';break;case"u":{const m=this.src.slice(this.i,this.i+4);/^[0-9a-fA-F]{4}$/.test(m)&&(d+=String.fromCharCode(parseInt(m,16)),this.i+=4);break}default:d+=h??""}continue}if(y===r)return this.i++,d;d+=y,this.i++}throw new Error("字符串未闭合")}ident(){const r=/^[A-Za-z_][A-Za-z0-9_]*/.exec(this.src.slice(this.i));if(!r)throw new Error("标识符格式错误");return this.i+=r[0].length,r[0]}number(){const r=/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/.exec(this.src.slice(this.i));if(!r||!r[0])throw new Error(`无法解析的值: ${this.src.slice(this.i,this.i+12)}`);return this.i+=r[0].length,Number(r[0])}}function Re(k){if(!k)return null;try{const r=pl(k);if(!r)return null;const d=new yl(r).parse();if(!Array.isArray(d))return null;const y=[];for(const h of d){if(!h||typeof h!="object"||Array.isArray(h))continue;const m=h,t=String(m.name??"").trim();if(!t)continue;const P=String(m.type??"text"),D=P==="select"||P==="multiselect"?P:"text",H=Array.isArray(m.options)?m.options.map(L=>{const j=L??{};return{value:String(j.value??""),label:j.label!=null?String(j.label):void 0}}).filter(L=>L.value!==""):void 0;y.push({name:t,label:m.label!=null?String(m.label):void 0,type:D,required:m.required===!0,placeholder:m.placeholder!=null?String(m.placeholder):void 0,help:m.help!=null?String(m.help):void 0,options:H})}return y.length?y:null}catch{return null}}function Be(k,r){const d={},y=new Set;for(const m of k){const t=r.indexOf(m.name);if(t===-1||t+1>=r.length)continue;const P=r[t+1];P.startsWith("--")||(y.add(t),y.add(t+1),d[m.name]=m.type==="multiselect"?P.split(",").map(D=>D.trim()).filter(Boolean):P)}const h=r.filter((m,t)=>!y.has(t));return{values:d,extra:h}}function He(k,r,d=[]){const y=[];for(const h of k){const m=r[h.name];if(h.type==="multiselect"){const t=Array.isArray(m)?m:[];t.length&&y.push(h.name,t.join(","))}else{const t=typeof m=="string"?m.trim():"";t&&y.push(h.name,t)}}return y.push(...d),y}const Je=[1,2,3,4,5,6,0],Ke={1:"周一",2:"周二",3:"周三",4:"周四",5:"周五",6:"周六",0:"周日"},Ye=[0,1,2,3,4,5,6];function je(k,r){if(!Number.isFinite(k))return 0;const d=Math.round(k);return Math.max(0,Math.min(r,d))}function Ve(k){return(k%7+7)%7}function Qe(k){const r=(k??"").trim();if(!r)return null;const d=r.split(/\s+/);if(d.length!==5)return null;const[y,h,m,t,P]=d;if(m!=="*"||t!=="*"||!/^\d{1,2}$/.test(y)||!/^\d{1,2}$/.test(h))return null;const D=Number(y),H=Number(h);if(D>59||H>23)return null;const L=gl(P);return L?{hour:H,minute:D,weekdays:L}:null}function gl(k){const r=k.trim();if(r==="*"||r==="?")return[...Ye];const d=new Set;for(const y of r.split(",")){const h=y.trim();if(!h||h.includes("/"))return null;const m=/^(\d)(?:-(\d))?$/.exec(h);if(!m)return null;const t=Number(m[1]),P=m[2]===void 0?t:Number(m[2]);if(t>7||P>7||t>P)return null;for(let D=t;D<=P;D++)d.add(Ve(D))}return d.size>0?[...d].sort((y,h)=>y-h):null}function kl(k,r,d){const y=je(k,59),h=je(r,23),m=[...new Set((d??[]).map(Ve))].sort((P,D)=>P-D),t=m.length===0||m.length===7?"*":m.join(",");return`${y} ${h} * * ${t}`}function Ge(k){const r=Qe(k);if(!r)return null;const d=`${String(r.hour).padStart(2,"0")}:${String(r.minute).padStart(2,"0")}`;return r.weekdays.length===7?`每天 ${d}`:`每${Je.filter(m=>r.weekdays.includes(m)).map(m=>Ke[m]??String(m)).map((m,t)=>t===0?m:m.replace(/^周/,"")).join("、")} ${d}`}const hl=[{label:"每天",weekdays:[...Ye]},{label:"工作日",weekdays:[1,2,3,4,5]},{label:"周末",weekdays:[6,0]}];function bl(k,r){const d=[...new Set(k.map(Ve))].sort((h,m)=>h-m).join(","),y=[...new Set(r.map(Ve))].sort((h,m)=>h-m).join(",");return d===y}const Vl={class:"week-picker"},_l={class:"week-presets"},wl={class:"cron-summary"},xl={class:"cron-summary-text"},Sl={key:1,class:"hint block"},Tl={class:"py-import"},Cl={class:"py-row"},$l={class:"py-name"},El={key:0,class:"py-param-tip"},Pl={key:3,class:"hint block"},Ul={key:0,class:"py-ip-list"},Nl={key:1,class:"hint block py-ip-none"},Al={key:0,class:"hint block"},ql=Ie({__name:"TaskFormDialog",props:{modelValue:{type:Boolean},task:{},actions:{}},emits:["update:modelValue","save"],setup(k,{emit:r}){const d=k,y=r,h=be({get:()=>d.modelValue,set:v=>y("update:modelValue",v)});function m(){return{name:"",type:ie.MANUAL,trigger:{type:"manual",datetime:null,cron:null,delaySeconds:null,intervalMinutes:null,idleMinutes:null,maxExecutions:-1,holidayCheck:!1},action:"show_reminder",actionParams:{},scriptPath:"",interpreter:null,scriptArgs:[],scriptTimeout:120,scriptWorkDir:null,retryCount:0,enabled:!0,notifyChannels:["desktop"],chainNext:null,chainCondition:null,oneTime:!1}}const t=w(m()),P=w(""),D=w([]),H=w([]),L=w([]),j=w(120),G=w(600),Z=w(""),z=w(""),B=w(""),$=w(null),A=w({}),X=w([]),re={ssh_command:"🐧 Linux 执行 Shell 命令",jenkins_build:"🔧 触发 Jenkins 构建",python_script:"🐍 本地 Python 脚本",show_reminder:"🔔 桌面提醒",http_request:"🌐 HTTP 请求",open_app:"🚀 打开程序 / 网址",volume_control:"🔊 音量控制",screenshot:"📸 截图",send_keystroke:"⌨️ 模拟按键",task_chain:"🔗 触发其他任务",clipboard_watch:"📋 剪贴板监听",lock_screen:"🔒 锁屏",open_recycle_bin:"🗑 打开回收站",refresh_desktop:"🔄 刷新桌面",clear_clipboard:"📌 清空剪贴板"},ve=be(()=>d.actions.map(v=>({value:v,label:re[v]??v})));function ne(v,l){const g=Number(v);return Number.isFinite(g)&&g>0?Math.round(g/1e3):l}Ne(()=>[d.modelValue,d.task],([v])=>{if(!v)return;d.task?(t.value=JSON.parse(JSON.stringify(d.task.config)),P.value=(t.value.scriptArgs??[]).join(" ")):(t.value=m(),P.value="");const l=t.value.actionParams??{};j.value=ne(l.timeoutMs,120),G.value=ne(l.timeoutMs,600);const g=l.params;Z.value=typeof g=="string"?g:g?JSON.stringify(g,null,2):"",z.value=typeof l.scriptContent=="string"?l.scriptContent:"",B.value=typeof l.scriptName=="string"?l.scriptName:"",ue("restore"),fe(),W.listTasks().then(c=>{D.value=c.filter(E=>{var Y;return E.id!==((Y=d.task)==null?void 0:Y.id)})}),W.listServers().then(c=>{H.value=c.servers}).catch(()=>{H.value=[]}),W.listInterpreters().then(c=>{L.value=c.interpreters}).catch(()=>{L.value=[]})});function ue(v){const l=Re(z.value);$.value=l;const g=A.value,c={};for(const E of l??[])c[E.name]=E.type==="multiselect"?[]:"";if(l&&v==="restore"){const E=Be(l,t.value.scriptArgs??[]);for(const[Y,F]of Object.entries(E.values))c[Y]=F;A.value=c,X.value=E.extra}else if(l&&v==="preserve"){for(const E of l)g[E.name]!==void 0&&(c[E.name]=g[E.name]);A.value=c}else A.value=c,X.value=[]}const pe=w(null);function _e(){var v;(v=pe.value)==null||v.click()}async function we(v){var c;const l=v.target,g=(c=l.files)==null?void 0:c[0];if(g)try{z.value=await g.text(),B.value=g.name,t.value.scriptArgs=[],ue("reset")}catch(E){N.error(`读取文件失败: ${String(E)}`)}finally{l.value=""}}function oe(){z.value="",B.value="",$.value=null,A.value={},X.value=[]}async function de(){var g,c;const v=t.value;if(!v.name.trim()){N.warning("请填写任务名称");return}if(v.type===ie.SCHEDULED&&v.trigger.type===te.CRON)if(I.value){if(!((g=v.trigger.cron)!=null&&g.trim())){N.warning("请填写 cron 表达式");return}}else{if(!K.value.length){N.warning("请至少选择一天(或点「每天」「工作日」「周末」快捷选择)");return}if(ee(),!((c=v.trigger.cron)!=null&&c.trim())){N.warning("执行时间无效,请重新选择");return}}if(v.action==="python_script"){if(!z.value.trim()){N.warning("请先导入 .py 文件或粘贴脚本代码");return}if($.value&&$.value.length){for(const E of $.value){if(!E.required)continue;const Y=A.value[E.name];if(E.type==="multiselect"?!(Array.isArray(Y)&&Y.length):!String(Y??"").trim()){N.warning(`请填写「${E.label||E.name}」`);return}}v.scriptArgs=He($.value,A.value,X.value)}v.actionParams={...v.actionParams,scriptContent:z.value,scriptName:B.value||"script.py"}}if(v.action==="ssh_command"){if(!String(v.actionParams.serverId??"").trim()){N.warning("请选择 Linux 服务器");return}if(!String(v.actionParams.command??"").trim()){N.warning("请填写要执行的命令");return}v.actionParams={...v.actionParams,timeoutMs:Math.max(1,j.value)*1e3}}if(v.action==="jenkins_build"){if(!String(v.actionParams.jobName??"").trim()){N.warning("请填写 Jenkins Job 名称");return}v.actionParams={...v.actionParams,params:Z.value,timeoutMs:Math.max(1,G.value)*1e3}}v.action==="python_script"&&!!$.value&&$.value.length>0||(v.scriptArgs=P.value.trim()?P.value.trim().split(/\s+/):[]),y("save",JSON.parse(JSON.stringify(v)))}Ne(()=>t.value.action,v=>{var g;const l=t.value.actionParams??{};v==="show_reminder"&&Object.keys(l).length===0&&(t.value.actionParams={text:"该干活啦!"}),v==="http_request"&&!l.url&&(t.value.actionParams={url:"",method:"GET",timeoutMs:15e3}),v==="ssh_command"&&!("command"in l)&&(t.value.actionParams={serverId:((g=H.value[0])==null?void 0:g.id)??"",command:"",timeoutMs:12e4},j.value=120),v==="jenkins_build"&&!("jobName"in l)&&(t.value.actionParams={jobName:"",params:"",timeoutMs:6e5},G.value=600,Z.value="")});const me=[{value:te.ONCE,label:"单次定时"},{value:te.CRON,label:"周期(每周)"},{value:te.DELAY,label:"延时执行"},{value:te.INTERVAL,label:"间隔循环"}],O=w("09:00"),K=w([1,2,3,4,5]),I=w(!1);function fe(){var g;const v=String(((g=t.value.trigger)==null?void 0:g.cron)??"").trim(),l=Qe(v);l?(O.value=`${String(l.hour).padStart(2,"0")}:${String(l.minute).padStart(2,"0")}`,K.value=[...l.weekdays],I.value=!1):v?I.value=!0:(O.value="09:00",K.value=[1,2,3,4,5],I.value=!1)}function ee(){if(I.value)return;const[v,l]=O.value.split(":"),g=Number(v??0),c=Number(l??0);!Number.isFinite(g)||!Number.isFinite(c)||(t.value.trigger.cron=kl(c,g,K.value))}Ne([O,K,I],()=>{ee()});function xe(v){K.value=[...v]}const Se=be(()=>{var v;return Ge((v=t.value.trigger)==null?void 0:v.cron)});function Te(v){return bl(K.value,v)}const Ce=[{value:he.IDLE,label:"闲置触发"},{value:he.STARTUP,label:"开机启动"},{value:he.NETWORK,label:"联网触发"}];return(v,l)=>{const g=S("el-input"),c=S("el-form-item"),E=S("el-radio-button"),Y=S("el-radio-group"),F=S("el-option"),R=S("el-select"),$e=S("el-time-picker"),ye=S("el-checkbox-button"),ge=S("el-checkbox-group"),le=S("el-button"),ae=S("el-checkbox"),Q=S("el-input-number"),Ee=S("el-switch"),s=S("el-divider"),n=S("el-form"),M=S("el-dialog");return o(),V(M,{modelValue:h.value,"onUpdate:modelValue":l[42]||(l[42]=e=>h.value=e),title:k.task?"编辑任务":"新建任务",width:"640px","destroy-on-close":"","close-on-click-modal":!1},{footer:u(()=>[a(le,{onClick:l[41]||(l[41]=e=>h.value=!1)},{default:u(()=>[...l[63]||(l[63]=[_("取消",-1)])]),_:1}),a(le,{type:"primary",onClick:de},{default:u(()=>[...l[64]||(l[64]=[_("保存",-1)])]),_:1})]),default:u(()=>[a(n,{"label-width":"92px","label-position":"right"},{default:u(()=>[a(c,{label:"任务名称",required:""},{default:u(()=>[a(g,{modelValue:t.value.name,"onUpdate:modelValue":l[0]||(l[0]=e=>t.value.name=e),placeholder:"例如:填写日报",maxlength:"40"},null,8,["modelValue"])]),_:1}),a(c,{label:"任务类型"},{default:u(()=>[a(Y,{modelValue:t.value.type,"onUpdate:modelValue":l[1]||(l[1]=e=>t.value.type=e)},{default:u(()=>[a(E,{value:J(ie).MANUAL},{default:u(()=>[...l[43]||(l[43]=[_("手动",-1)])]),_:1},8,["value"]),a(E,{value:J(ie).SCHEDULED},{default:u(()=>[...l[44]||(l[44]=[_("定时",-1)])]),_:1},8,["value"]),a(E,{value:J(ie).SCENE},{default:u(()=>[...l[45]||(l[45]=[_("场景",-1)])]),_:1},8,["value"])]),_:1},8,["modelValue"])]),_:1}),t.value.type===J(ie).SCHEDULED?(o(),f(C,{key:0},[a(c,{label:"调度方式"},{default:u(()=>[a(R,{modelValue:t.value.trigger.type,"onUpdate:modelValue":l[2]||(l[2]=e=>t.value.trigger.type=e),style:{width:"200px"}},{default:u(()=>[(o(),f(C,null,q(me,e=>a(F,{key:e.value,label:e.label,value:e.value},null,8,["label","value"])),64))]),_:1},8,["modelValue"])]),_:1}),t.value.trigger.type===J(te).CRON?(o(),f(C,{key:0},[a(c,{label:"执行时间"},{default:u(()=>[a($e,{modelValue:O.value,"onUpdate:modelValue":l[3]||(l[3]=e=>O.value=e),format:"HH:mm","value-format":"HH:mm",placeholder:"选择时间",style:{width:"160px"},clearable:!1},null,8,["modelValue"])]),_:1}),a(c,{label:"重复"},{default:u(()=>[p("div",Vl,[a(ge,{modelValue:K.value,"onUpdate:modelValue":l[4]||(l[4]=e=>K.value=e)},{default:u(()=>[(o(!0),f(C,null,q(J(Je),e=>(o(),V(ye,{key:e,value:e},{default:u(()=>[_(x(J(Ke)[e]),1)]),_:2},1032,["value"]))),128))]),_:1},8,["modelValue"]),p("div",_l,[(o(!0),f(C,null,q(J(hl),e=>(o(),V(le,{key:e.label,size:"small",type:Te(e.weekdays)?"primary":"default",onClick:T=>xe(e.weekdays)},{default:u(()=>[_(x(e.label),1)]),_:2},1032,["type","onClick"]))),128))])])]),_:1}),a(c,null,{default:u(()=>[p("div",wl,[p("span",xl,x(Se.value??"请至少选择一天"),1),a(ae,{modelValue:I.value,"onUpdate:modelValue":l[5]||(l[5]=e=>I.value=e),size:"small",class:"cron-manual-toggle"},{default:u(()=>[...l[46]||(l[46]=[_(" 手动编辑 cron 表达式 ",-1)])]),_:1},8,["modelValue"])]),I.value?(o(),V(g,{key:0,modelValue:t.value.trigger.cron,"onUpdate:modelValue":l[6]||(l[6]=e=>t.value.trigger.cron=e),placeholder:"55 17 * * 1-5",class:"cron-input"},null,8,["modelValue"])):b("",!0),I.value?(o(),f("div",Sl," 格式:分 时 日 月 周几(周几 0=周日 … 6=周六)。保存后无法用「周几+时间」表示时会自动切到此处编辑。 ")):b("",!0)]),_:1})],64)):b("",!0),t.value.trigger.type===J(te).ONCE?(o(),V(c,{key:1,label:"执行时间"},{default:u(()=>[a(g,{modelValue:t.value.trigger.datetime,"onUpdate:modelValue":l[7]||(l[7]=e=>t.value.trigger.datetime=e),placeholder:"2026-08-25 09:30"},null,8,["modelValue"])]),_:1})):b("",!0),t.value.trigger.type===J(te).DELAY?(o(),V(c,{key:2,label:"延时(秒)"},{default:u(()=>[a(Q,{modelValue:t.value.trigger.delaySeconds,"onUpdate:modelValue":l[8]||(l[8]=e=>t.value.trigger.delaySeconds=e),min:1,max:86400},null,8,["modelValue"])]),_:1})):b("",!0),t.value.trigger.type===J(te).INTERVAL?(o(),V(c,{key:3,label:"间隔(分钟)"},{default:u(()=>[a(Q,{modelValue:t.value.trigger.intervalMinutes,"onUpdate:modelValue":l[9]||(l[9]=e=>t.value.trigger.intervalMinutes=e),min:1,max:1440},null,8,["modelValue"])]),_:1})):b("",!0),a(c,{label:"工作日检测"},{default:u(()=>[a(Ee,{modelValue:t.value.trigger.holidayCheck,"onUpdate:modelValue":l[10]||(l[10]=e=>t.value.trigger.holidayCheck=e),"active-text":"周末跳过"},null,8,["modelValue"])]),_:1}),a(c,{label:"最大次数"},{default:u(()=>[a(Q,{modelValue:t.value.trigger.maxExecutions,"onUpdate:modelValue":l[11]||(l[11]=e=>t.value.trigger.maxExecutions=e),min:-1,max:9999},null,8,["modelValue"]),l[47]||(l[47]=p("span",{class:"hint"},"-1 = 无限",-1))]),_:1})],64)):b("",!0),t.value.type===J(ie).SCENE?(o(),f(C,{key:1},[a(c,{label:"触发场景"},{default:u(()=>[a(R,{modelValue:t.value.trigger.type,"onUpdate:modelValue":l[12]||(l[12]=e=>t.value.trigger.type=e),style:{width:"200px"}},{default:u(()=>[(o(),f(C,null,q(Ce,e=>a(F,{key:e.value,label:e.label,value:e.value},null,8,["label","value"])),64))]),_:1},8,["modelValue"])]),_:1}),t.value.trigger.type===J(he).IDLE?(o(),V(c,{key:0,label:"闲置(分钟)"},{default:u(()=>[a(Q,{modelValue:t.value.trigger.idleMinutes,"onUpdate:modelValue":l[13]||(l[13]=e=>t.value.trigger.idleMinutes=e),min:1,max:720},null,8,["modelValue"])]),_:1})):b("",!0)],64)):b("",!0),a(c,{label:"执行动作"},{default:u(()=>[a(R,{modelValue:t.value.action,"onUpdate:modelValue":l[14]||(l[14]=e=>t.value.action=e),style:{width:"280px"}},{default:u(()=>[(o(!0),f(C,null,q(ve.value,e=>(o(),V(F,{key:e.value,label:e.label,value:e.value},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),t.value.action==="python_script"?(o(),f(C,{key:2},[a(c,{label:"Python 脚本",required:""},{default:u(()=>[p("div",Tl,[p("div",Cl,[a(le,{size:"small",onClick:_e},{default:u(()=>[...l[48]||(l[48]=[_("导入 .py 文件",-1)])]),_:1}),p("input",{ref_key:"pyFileInput",ref:pe,type:"file",accept:".py,.txt",hidden:"",onChange:we},null,544),p("span",$l,x(B.value||"未导入"),1),z.value?(o(),V(le,{key:0,size:"small",type:"danger",link:"",onClick:oe},{default:u(()=>[...l[49]||(l[49]=[_(" 清除 ",-1)])]),_:1})):b("",!0),z.value?(o(),V(le,{key:1,size:"small",link:"",onClick:l[15]||(l[15]=e=>ue("preserve"))},{default:u(()=>[...l[50]||(l[50]=[_(" 重新解析参数 ",-1)])]),_:1})):b("",!0)]),a(g,{modelValue:z.value,"onUpdate:modelValue":l[16]||(l[16]=e=>z.value=e),type:"textarea",rows:10,class:"py-code",placeholder:"# 点击上方按钮导入 .py 文件,或直接在此粘贴脚本代码"},null,8,["modelValue"]),l[51]||(l[51]=p("div",{class:"hint block"}," 脚本保存在任务内,每次执行时运行(不依赖本机文件路径)。 运行时会把「系统设置」中的 Jenkins / 服务器配置注入给脚本(环境变量 DESKPET_CONFIG) ",-1)),$.value&&$.value.length?(o(),f("div",El," 已识别脚本内 "+x($.value.length)+" 个参数(TASK_PARAMS),可在下方选择/填写 ",1)):b("",!0)])]),_:1}),a(c,{label:"运行服务器"},{default:u(()=>[a(R,{modelValue:t.value.actionParams.serverId,"onUpdate:modelValue":l[17]||(l[17]=e=>t.value.actionParams.serverId=e),clearable:"",placeholder:"可选:脚本要连接的 Linux 服务器",style:{width:"320px"}},{default:u(()=>[(o(!0),f(C,null,q(H.value,e=>(o(),V(F,{key:e.id,value:e.id,label:`${e.name}(${e.username}@${e.host})`},null,8,["value","label"]))),128))]),_:1},8,["modelValue"]),l[52]||(l[52]=p("span",{class:"hint"},"不选则脚本自行从配置的服务器列表中选择",-1))]),_:1}),$.value&&$.value.length?(o(!0),f(C,{key:0},q($.value,e=>(o(),V(c,{key:e.name,label:e.label||e.name,required:!!e.required},{default:u(()=>[e.type==="multiselect"?(o(),V(R,{key:0,modelValue:A.value[e.name],"onUpdate:modelValue":T=>A.value[e.name]=T,multiple:"",filterable:"",placeholder:"可多选",style:{width:"320px"}},{default:u(()=>[(o(!0),f(C,null,q(e.options||[],T=>(o(),V(F,{key:T.value,value:T.value,label:T.label||T.value},null,8,["value","label"]))),128))]),_:2},1032,["modelValue","onUpdate:modelValue"])):e.type==="select"?(o(),V(R,{key:1,modelValue:A.value[e.name],"onUpdate:modelValue":T=>A.value[e.name]=T,clearable:"",placeholder:"请选择",style:{width:"320px"}},{default:u(()=>[(o(!0),f(C,null,q(e.options||[],T=>(o(),V(F,{key:T.value,value:T.value,label:T.label||T.value},null,8,["value","label"]))),128))]),_:2},1032,["modelValue","onUpdate:modelValue"])):(o(),V(g,{key:2,modelValue:A.value[e.name],"onUpdate:modelValue":T=>A.value[e.name]=T,placeholder:e.placeholder||"",style:{width:"320px"}},null,8,["modelValue","onUpdate:modelValue","placeholder"])),e.help?(o(),f("div",Pl,x(e.help),1)):b("",!0)]),_:2},1032,["label","required"]))),128)):b("",!0),a(c,{label:"解释器"},{default:u(()=>[a(R,{modelValue:t.value.interpreter,"onUpdate:modelValue":l[18]||(l[18]=e=>t.value.interpreter=e),clearable:"",filterable:"","allow-create":"","default-first-option":"",placeholder:"留空自动探测(推荐)",style:{width:"320px"}},{default:u(()=>[(o(!0),f(C,null,q(L.value,e=>(o(),V(F,{key:e.command,value:e.command,label:`${e.name} → ${e.command}`},null,8,["value","label"]))),128))]),_:1},8,["modelValue"]),l[54]||(l[54]=p("div",{class:"hint block"}," 留空时自动探测(Windows 依次尝试 python / python3 / py,并自动跳过 Microsoft Store 的假 python 存根)。脚本依赖第三方库时,请选装了这些库的解释器。 ",-1)),L.value.length?(o(),f("div",Ul,[l[53]||(l[53]=p("span",{class:"py-ip-tip"},"本机检测到:",-1)),(o(!0),f(C,null,q(L.value,e=>(o(),f("span",{key:e.command,class:"py-ip-item"},x(e.name)+" · "+x(e.command),1))),128))])):(o(),f("div",Nl," 未探测到可用解释器,请手动填写完整路径(如 C:\\Program Files\\Python312\\python.exe) "))]),_:1}),$.value&&$.value.length?b("",!0):(o(),V(c,{key:1,label:"脚本参数"},{default:u(()=>[a(g,{modelValue:P.value,"onUpdate:modelValue":l[19]||(l[19]=e=>P.value=e),placeholder:"--key value --flag"},null,8,["modelValue"])]),_:1})),a(c,{label:"超时(秒)"},{default:u(()=>[a(Q,{modelValue:t.value.scriptTimeout,"onUpdate:modelValue":l[20]||(l[20]=e=>t.value.scriptTimeout=e),min:10,max:1800},null,8,["modelValue"])]),_:1}),a(c,{label:"工作目录"},{default:u(()=>[a(g,{modelValue:t.value.scriptWorkDir,"onUpdate:modelValue":l[21]||(l[21]=e=>t.value.scriptWorkDir=e),placeholder:"可选,脚本运行时的工作目录"},null,8,["modelValue"])]),_:1})],64)):b("",!0),t.value.action==="show_reminder"?(o(),V(c,{key:3,label:"提醒内容"},{default:u(()=>[a(g,{modelValue:t.value.actionParams.text,"onUpdate:modelValue":l[22]||(l[22]=e=>t.value.actionParams.text=e),type:"textarea",rows:2},null,8,["modelValue"]),l[55]||(l[55]=p("div",{class:"hint block"}," 触发后在管理台弹出提醒,并发送一条系统通知(桌面级全屏/气泡提醒已移除) ",-1))]),_:1})):b("",!0),t.value.action==="open_app"?(o(),f(C,{key:4},[a(c,{label:"URL"},{default:u(()=>[a(g,{modelValue:t.value.actionParams.url,"onUpdate:modelValue":l[23]||(l[23]=e=>t.value.actionParams.url=e),placeholder:"https://..."},null,8,["modelValue"])]),_:1}),a(c,{label:"文件路径"},{default:u(()=>[a(g,{modelValue:t.value.actionParams.target,"onUpdate:modelValue":l[24]||(l[24]=e=>t.value.actionParams.target=e),placeholder:"/Users/... 或文件夹"},null,8,["modelValue"])]),_:1}),a(c,{label:"应用名"},{default:u(()=>[a(g,{modelValue:t.value.actionParams.app,"onUpdate:modelValue":l[25]||(l[25]=e=>t.value.actionParams.app=e),placeholder:"例如 WeChat / Safari"},null,8,["modelValue"])]),_:1})],64)):b("",!0),t.value.action==="http_request"?(o(),f(C,{key:5},[a(c,{label:"URL",required:""},{default:u(()=>[a(g,{modelValue:t.value.actionParams.url,"onUpdate:modelValue":l[26]||(l[26]=e=>t.value.actionParams.url=e),placeholder:"https://api.example.com/webhook"},null,8,["modelValue"])]),_:1}),a(c,{label:"Method"},{default:u(()=>[a(R,{modelValue:t.value.actionParams.method,"onUpdate:modelValue":l[27]||(l[27]=e=>t.value.actionParams.method=e),style:{width:"120px"}},{default:u(()=>[(o(),f(C,null,q(["GET","POST","PUT","DELETE"],e=>a(F,{key:e,label:e,value:e},null,8,["label","value"])),64))]),_:1},8,["modelValue"])]),_:1}),a(c,{label:"Body"},{default:u(()=>[a(g,{modelValue:t.value.actionParams.body,"onUpdate:modelValue":l[28]||(l[28]=e=>t.value.actionParams.body=e),type:"textarea",rows:2,placeholder:'{"key": "value"}'},null,8,["modelValue"])]),_:1})],64)):b("",!0),t.value.action==="ssh_command"?(o(),f(C,{key:6},[a(c,{label:"服务器",required:""},{default:u(()=>[a(R,{modelValue:t.value.actionParams.serverId,"onUpdate:modelValue":l[29]||(l[29]=e=>t.value.actionParams.serverId=e),placeholder:"选择 Linux 服务器",style:{width:"320px"}},{default:u(()=>[(o(!0),f(C,null,q(H.value,e=>(o(),V(F,{key:e.id,value:e.id,label:`${e.name}(${e.username}@${e.host})`},null,8,["value","label"]))),128))]),_:1},8,["modelValue"]),H.value.length?b("",!0):(o(),f("div",Al," 还没有服务器,请先到「系统设置 → Linux 服务器」添加 "))]),_:1}),a(c,{label:"命令",required:""},{default:u(()=>[a(g,{modelValue:t.value.actionParams.command,"onUpdate:modelValue":l[30]||(l[30]=e=>t.value.actionParams.command=e),type:"textarea",rows:4,placeholder:"例如:cd /opt/app && sh deploy.sh"},null,8,["modelValue"])]),_:1}),a(c,{label:"超时(秒)"},{default:u(()=>[a(Q,{modelValue:j.value,"onUpdate:modelValue":l[31]||(l[31]=e=>j.value=e),min:5,max:3600},null,8,["modelValue"])]),_:1})],64)):b("",!0),t.value.action==="jenkins_build"?(o(),f(C,{key:7},[a(c,{label:"Job 名称",required:""},{default:u(()=>[a(g,{modelValue:t.value.actionParams.jobName,"onUpdate:modelValue":l[32]||(l[32]=e=>t.value.actionParams.jobName=e),placeholder:"例如 my-job 或 folder/my-job"},null,8,["modelValue"])]),_:1}),a(c,{label:"构建参数"},{default:u(()=>[a(g,{modelValue:Z.value,"onUpdate:modelValue":l[33]||(l[33]=e=>Z.value=e),type:"textarea",rows:3,placeholder:"可选:每行一条 key=value,或 JSON 对象"},null,8,["modelValue"])]),_:1}),a(c,{label:"等待超时(秒)"},{default:u(()=>[a(Q,{modelValue:G.value,"onUpdate:modelValue":l[34]||(l[34]=e=>G.value=e),min:10,max:7200},null,8,["modelValue"]),l[56]||(l[56]=p("span",{class:"hint"},"等待构建完成的最长时间",-1))]),_:1})],64)):b("",!0),a(c,{label:"失败重试"},{default:u(()=>[a(Q,{modelValue:t.value.retryCount,"onUpdate:modelValue":l[35]||(l[35]=e=>t.value.retryCount=e),min:0,max:10},null,8,["modelValue"]),l[57]||(l[57]=p("span",{class:"hint"},"次",-1))]),_:1}),a(c,{label:"通知通道"},{default:u(()=>[a(ge,{modelValue:t.value.notifyChannels,"onUpdate:modelValue":l[36]||(l[36]=e=>t.value.notifyChannels=e)},{default:u(()=>[a(ae,{value:"desktop"},{default:u(()=>[...l[58]||(l[58]=[_("桌面通知",-1)])]),_:1}),a(ae,{value:"wechat"},{default:u(()=>[...l[59]||(l[59]=[_("微信推送",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),a(c,{label:"其他选项"},{default:u(()=>[a(ae,{modelValue:t.value.enabled,"onUpdate:modelValue":l[37]||(l[37]=e=>t.value.enabled=e)},{default:u(()=>[...l[60]||(l[60]=[_("启用",-1)])]),_:1},8,["modelValue"]),a(ae,{modelValue:t.value.oneTime,"onUpdate:modelValue":l[38]||(l[38]=e=>t.value.oneTime=e)},{default:u(()=>[...l[61]||(l[61]=[_("一次性(执行后删除)",-1)])]),_:1},8,["modelValue"])]),_:1}),a(s,{"content-position":"left"},{default:u(()=>[...l[62]||(l[62]=[_("任务链(完成后自动触发下一个)",-1)])]),_:1}),a(c,{label:"下一任务"},{default:u(()=>[a(R,{modelValue:t.value.chainNext,"onUpdate:modelValue":l[39]||(l[39]=e=>t.value.chainNext=e),clearable:"",filterable:"",placeholder:"选择链式后续任务",style:{width:"280px"}},{default:u(()=>[(o(!0),f(C,null,q(D.value,e=>(o(),V(F,{key:e.id,value:e.id,label:e.config.name},null,8,["value","label"]))),128))]),_:1},8,["modelValue"])]),_:1}),t.value.chainNext?(o(),V(c,{key:8,label:"触发条件"},{default:u(()=>[a(g,{modelValue:t.value.chainCondition,"onUpdate:modelValue":l[40]||(l[40]=e=>t.value.chainCondition=e),placeholder:"留空=成功时触发;支持 exit==0 / output contains xxx / failed"},null,8,["modelValue"])]),_:1})):b("",!0)]),_:1})]),_:1},8,["modelValue","title"])}}}),Ll=Fe(ql,[["__scopeId","data-v-137fad9b"]]),Ml={class:"page"},Dl={class:"toolbar"},Wl={class:"toolbar-right"},jl={class:"hint"},zl={class:"queue-head"},Ol={class:"queue-title"},Il={class:"queue-actions"},Fl={class:"queue-items"},Rl={key:0,class:"q-item q-running"},Bl={key:1,class:"q-empty"},Hl={class:"card table-card"},Jl={key:0,class:"q-pos"},Kl={key:3,class:"run-help"},Yl={class:"live-console"},Ql={class:"live-head"},Gl={class:"live-state"},Zl={key:0},Xl={key:1,class:"live-err"},et={key:2,class:"live-empty"},lt={class:"log-head"},tt={class:"log-duration"},at={key:0,class:"log-error"},nt={key:1,class:"log-detail"},ut={key:2,class:"log-detail"},ze=64*1024,Oe=10,ot=Ie({__name:"TasksView",setup(k){const r=w([]),d=w([]),y=w(!1),h=w(""),m=w({running:null,queue:[]});function t(s){const n=m.value.queue.findIndex(M=>M.id===s);return n===-1?0:n+1}async function P(){try{m.value=await W.getQueue()}catch{}}async function D(){await ke.confirm(`确定清空排队中的 ${m.value.queue.length} 个任务?(正在运行的任务不受影响)`,"清空队列",{type:"warning",confirmButtonText:"清空",cancelButtonText:"取消"});const s=await W.clearQueue();N.success(`已清空 ${s.cleared} 个排队任务`),await ee()}async function H(){const s=m.value.running?`「${m.value.running.name}」`:"(无运行中任务)";await ke.confirm(`确定全部停止?将终止运行中的任务 ${s} 并清空 ${m.value.queue.length} 个排队任务。`,"全部停止",{type:"warning",confirmButtonText:"全部停止",cancelButtonText:"取消"});const n=await W.stopAll();N.success(`已停止 ${n.stopped} 个运行中任务,清空 ${n.cleared} 个排队任务`),await ee()}const L=w(!1),j=w(null),G=w(!1),Z=w(null),z=w([]),B=w(""),$=w(""),A=w(!1),X=w(!0),re=w(null),ve=be(()=>{const s=z.value[0];if(!s||s.status!=="failed")return"";const n=s.error??"";return/服务重启|服务退出/.test(n)?n.includes("服务重启")?"上次执行被「服务重启」打断:这不是脚本自身的报错,而是执行过程中后端进程被重启了。产生的日志已保留;若脚本有副作用(如部署),请先确认远端状态再重跑。":"上次执行被「服务退出」正常收尾打断:非脚本自身报错,可直接重新运行。":""});function ne(s){return s.length>ze?s.slice(-ze):s}function ue(){const s=re.value;s&&X.value&&(s.scrollTop=s.scrollHeight)}function pe(s,n){s==="stderr"?$.value=ne($.value+n):B.value=ne(B.value+n),We(ue)}function _e(s){B.value=ne(s.stdout??""),$.value=ne(s.stderr??""),A.value=s.running,X.value=!0,We(ue)}function we(){const s=re.value;s&&(X.value=s.scrollHeight-s.scrollTop-s.clientHeight<24)}const oe=w(!1),de=w(null),me=w(null),O=w({}),K=w([]),I=w(!1);function fe(){const s=h.value.trim().toLowerCase();return s?r.value.filter(n=>n.config.name.toLowerCase().includes(s)||(le[n.config.action]??n.config.action).includes(s)||ae(n).toLowerCase().includes(s)):r.value}async function ee(){y.value=!0;try{r.value=await W.listTasks(),d.value=await W.listActions(),await P()}catch(s){N.error(`加载失败: ${String(s)}`)}finally{y.value=!1}}function xe(){j.value=null,L.value=!0}function Se(s){j.value=s,L.value=!0}async function Te(s){j.value?(await W.updateTask(j.value.id,s),N.success("任务已更新")):(await W.createTask(s),N.success("任务已创建")),L.value=!1,await ee()}function Ce(s){var M;if(s.config.action!=="python_script")return null;const n=String(((M=s.config.actionParams)==null?void 0:M.scriptContent)??"");return Re(n)}async function v(s){const n=Ce(s);if(n&&n.length){de.value=s,me.value=n;const e={};for(const se of n)e[se.name]=se.type==="multiselect"?[]:"";const T=Be(n,s.config.scriptArgs??[]);for(const[se,Pe]of Object.entries(T.values))e[se]=Pe;O.value=e,K.value=T.extra,oe.value=!0;return}(await W.runTask(s.id)).ok?N.success(`「${s.config.name}」已加入执行队列`):N.warning("任务未入队(可能正在运行或已排队)")}async function l(s=!1){const n=de.value;if(n){I.value=!0;try{const M=s?void 0:He(me.value??[],O.value,K.value);(await W.runTask(n.id,M)).ok?N.success(`「${n.config.name}」已加入执行队列(${s?"默认参数":"本次参数"})`):N.warning("任务未入队(可能正在运行或已排队)"),oe.value=!1}catch(M){N.error(`运行失败: ${String(M)}`)}finally{I.value=!1}}}async function g(s){if(!await W.stopTask(s.id)){N.warning("任务未在运行或排队");return}N.success(s.status==="running"?"已发送停止指令":"已取消排队")}async function c(s){await W.toggleTask(s.id),await ee()}async function E(s){await ke.confirm(`确定删除任务「${s.config.name}」?`,"删除确认",{type:"warning",confirmButtonText:"删除",cancelButtonText:"取消"}),await W.deleteTask(s.id),N.success("已删除"),await ee()}async function Y(s){Z.value=s,z.value=await W.taskLogs(s.id,Oe);try{_e(await W.taskOutput(s.id))}catch{B.value="",$.value="",A.value=!1}G.value=!0}async function F(s){const n=`${location.origin}/api/hooks/${s.id}`;try{await navigator.clipboard.writeText(n),N.success(`Webhook 地址已复制
|
|
5
|
+
${n}`)}catch{ke.alert(n,"Webhook 触发地址",{confirmButtonText:"知道了"})}}let R=null;rl(()=>{ee(),R=dl((s,n)=>{if(s==="queue-changed"){m.value=n;return}if(s==="task-output"){const M=n;G.value&&Z.value&&M.taskId===Z.value.id&&(A.value=!0,pe(M.stream,M.text));return}(s==="tasks-changed"||s==="task-status"||s==="execution")&&ee()})}),ml(()=>{R==null||R()});const $e={idle:"info",pending:"warning",running:"primary",completed:"success",failed:"danger",cancelled:"info",disabled:"info"},ye={idle:"空闲",pending:"排队中",running:"运行中",completed:"已完成",failed:"失败",cancelled:"已取消",disabled:"已禁用"},ge={manual:"手动",scheduled:"定时",scene:"场景"},le={ssh_command:"🐧 Linux 命令",jenkins_build:"🔧 Jenkins 构建",python_script:"🐍 脚本",show_reminder:"🔔 提醒",open_app:"🚀 打开程序",http_request:"🌐 HTTP 请求",volume_control:"🔊 音量",screenshot:"📸 截图",send_keystroke:"⌨️ 按键",task_chain:"🔗 任务链",clipboard_watch:"📋 剪贴板",lock_screen:"🔒 锁屏",open_recycle_bin:"🗑 回收站",refresh_desktop:"🔄 刷新桌面",clear_clipboard:"📌 清剪贴板"};function ae(s){const n=s.config.trigger;switch(n.type){case"cron":return Ge(n.cron)??`cron: ${n.cron}`;case"once":return`单次: ${n.datetime}`;case"delay":return`延时 ${n.delaySeconds}s`;case"interval":return`每 ${n.intervalMinutes} 分钟`;case"idle":return`闲置 ${n.idleMinutes} 分钟`;case"startup":return"开机时";case"network":return"联网时";default:return"-"}}function Q(s){return s?new Date(s).toLocaleString("zh-CN",{hour12:!1}):"-"}function Ee(s){return s==null?"-":s<1e3?`${s}ms`:`${(s/1e3).toFixed(1)}s`}return(s,n)=>{var Me,De;const M=S("el-input"),e=S("el-button"),T=S("el-table-column"),se=S("el-tag"),Pe=S("el-divider"),Ae=S("el-empty"),Ze=S("el-table"),qe=S("el-option"),Le=S("el-select"),Xe=S("el-form-item"),el=S("el-form"),ll=S("el-dialog"),tl=S("el-alert"),al=S("el-timeline-item"),nl=S("el-timeline"),ul=S("el-drawer"),ol=vl("loading");return o(),f("div",Ml,[p("div",Dl,[a(M,{modelValue:h.value,"onUpdate:modelValue":n[0]||(n[0]=i=>h.value=i),placeholder:"搜索任务名称 / 动作 / 触发方式…",clearable:"",class:"search"},{prefix:u(()=>[...n[9]||(n[9]=[p("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round"},[p("circle",{cx:"11",cy:"11",r:"7"}),p("path",{d:"m20 20-3.5-3.5"})],-1)])]),_:1},8,["modelValue"]),p("div",Wl,[p("span",jl,x(fe().length)+" / "+x(r.value.length)+" 个任务",1),a(e,{type:"primary",onClick:xe},{default:u(()=>[...n[10]||(n[10]=[_("+ 新建任务",-1)])]),_:1})])]),p("div",{class:ce(["queue-bar",{"q-busy":!!m.value.running}])},[p("div",zl,[p("span",Ol,[p("span",{class:ce(["q-live",{on:!!m.value.running}])},null,2),n[11]||(n[11]=_("执行队列 ",-1))]),n[13]||(n[13]=p("span",{class:"queue-sub"},"同一时刻只运行 1 个任务,其余按顺序排队",-1)),p("div",Il,[m.value.queue.length?(o(),V(e,{key:0,size:"small",onClick:D},{default:u(()=>[_(" 清空队列("+x(m.value.queue.length)+") ",1)]),_:1})):b("",!0),m.value.running||m.value.queue.length?(o(),V(e,{key:1,size:"small",type:"danger",plain:"",onClick:H},{default:u(()=>[...n[12]||(n[12]=[_(" 全部停止 ",-1)])]),_:1})):b("",!0)])]),p("div",Fl,[m.value.running?(o(),f("span",Rl," 执行中 · "+x(m.value.running.name),1)):b("",!0),(o(!0),f(C,null,q(m.value.queue,(i,U)=>(o(),f("span",{key:i.id,class:"q-item q-wait"}," 排队 "+x(U+1)+" · "+x(i.name),1))),128)),!m.value.running&&!m.value.queue.length?(o(),f("span",Bl,"空闲中")):b("",!0)])],2),p("div",Hl,[cl((o(),V(Ze,{data:fe(),style:{width:"100%"}},{empty:u(()=>[a(Ae,{description:h.value?"没有匹配的任务":"暂无任务,点击右上角新建"},null,8,["description"])]),default:u(()=>[a(T,{label:"状态",width:"132"},{default:u(({row:i})=>[p("span",{class:ce(["status-pill",`st-${i.status}`])},[n[14]||(n[14]=p("span",{class:"status-dot"},null,-1)),_(x(ye[i.status]??i.status),1)],2),i.status==="pending"&&t(i.id)?(o(),f("span",Jl," #"+x(t(i.id)),1)):b("",!0)]),_:1}),a(T,{label:"名称","min-width":"160"},{default:u(({row:i})=>[p("span",{class:ce(["task-name",{disabled:!i.config.enabled}])},x(i.config.name),3),i.config.oneTime?(o(),V(se,{key:0,size:"small",type:"warning",effect:"plain",class:"ml6"},{default:u(()=>[...n[15]||(n[15]=[_("一次性",-1)])]),_:1})):b("",!0)]),_:1}),a(T,{label:"类型",width:"70"},{default:u(({row:i})=>[_(x(ge[i.config.type]??i.config.type),1)]),_:1}),a(T,{label:"动作",width:"130"},{default:u(({row:i})=>[_(x(le[i.config.action]??i.config.action),1)]),_:1}),a(T,{label:"触发方式","min-width":"140"},{default:u(({row:i})=>[_(x(ae(i)),1)]),_:1}),a(T,{label:"上次运行",width:"160"},{default:u(({row:i})=>[_(x(Q(i.lastRunAt??i.createdAt)),1)]),_:1}),a(T,{label:"操作",width:"250",fixed:"right"},{default:u(({row:i})=>[a(e,{size:"small",type:"primary",link:"",onClick:U=>v(i)},{default:u(()=>[...n[16]||(n[16]=[_("▶ 运行",-1)])]),_:1},8,["onClick"]),a(Pe,{direction:"vertical"}),a(e,{size:"small",link:"",onClick:U=>Y(i)},{default:u(()=>[...n[17]||(n[17]=[_("日志",-1)])]),_:1},8,["onClick"]),a(e,{size:"small",link:"",title:"复制 Webhook 触发地址",onClick:U=>F(i)},{default:u(()=>[...n[18]||(n[18]=[_("Hook",-1)])]),_:1},8,["onClick"]),a(e,{size:"small",link:"",onClick:U=>Se(i)},{default:u(()=>[...n[19]||(n[19]=[_("编辑",-1)])]),_:1},8,["onClick"]),a(e,{size:"small",link:"",onClick:U=>c(i)},{default:u(()=>[_(x(i.config.enabled?"禁用":"启用"),1)]),_:2},1032,["onClick"]),i.status==="running"||i.status==="pending"?(o(),V(e,{key:0,size:"small",type:"warning",link:"",onClick:U=>g(i)},{default:u(()=>[_(x(i.status==="running"?"停止":"取消排队"),1)]),_:2},1032,["onClick"])):b("",!0),a(e,{size:"small",type:"danger",link:"",onClick:U=>E(i)},{default:u(()=>[...n[20]||(n[20]=[_("删除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[ol,y.value]])]),a(Ll,{modelValue:L.value,"onUpdate:modelValue":n[1]||(n[1]=i=>L.value=i),task:j.value,actions:d.value,onSave:Te},null,8,["modelValue","task","actions"]),a(ll,{modelValue:oe.value,"onUpdate:modelValue":n[5]||(n[5]=i=>oe.value=i),title:`运行任务 — ${((Me=de.value)==null?void 0:Me.config.name)??""}`,width:"520px","destroy-on-close":""},{footer:u(()=>[a(e,{onClick:n[2]||(n[2]=i=>oe.value=!1)},{default:u(()=>[...n[21]||(n[21]=[_("取消",-1)])]),_:1}),a(e,{loading:I.value,onClick:n[3]||(n[3]=i=>l(!0))},{default:u(()=>[...n[22]||(n[22]=[_("用默认参数运行",-1)])]),_:1},8,["loading"]),a(e,{type:"primary",loading:I.value,onClick:n[4]||(n[4]=i=>l(!1))},{default:u(()=>[...n[23]||(n[23]=[_("运行",-1)])]),_:1},8,["loading"])]),default:u(()=>[n[24]||(n[24]=p("div",{class:"run-tip"}," 已按任务默认参数填入,可直接运行或临时修改(仅本次生效,不改动任务默认值) ",-1)),a(el,{"label-width":"110px","label-position":"right"},{default:u(()=>[(o(!0),f(C,null,q(me.value||[],i=>(o(),V(Xe,{key:i.name,label:i.label||i.name},{default:u(()=>[i.type==="multiselect"?(o(),V(Le,{key:0,modelValue:O.value[i.name],"onUpdate:modelValue":U=>O.value[i.name]=U,multiple:"",filterable:"",placeholder:"可多选",style:{width:"100%"}},{default:u(()=>[(o(!0),f(C,null,q(i.options||[],U=>(o(),V(qe,{key:U.value,value:U.value,label:U.label||U.value},null,8,["value","label"]))),128))]),_:2},1032,["modelValue","onUpdate:modelValue"])):i.type==="select"?(o(),V(Le,{key:1,modelValue:O.value[i.name],"onUpdate:modelValue":U=>O.value[i.name]=U,clearable:"",placeholder:"请选择",style:{width:"100%"}},{default:u(()=>[(o(!0),f(C,null,q(i.options||[],U=>(o(),V(qe,{key:U.value,value:U.value,label:U.label||U.value},null,8,["value","label"]))),128))]),_:2},1032,["modelValue","onUpdate:modelValue"])):(o(),V(M,{key:2,modelValue:O.value[i.name],"onUpdate:modelValue":U=>O.value[i.name]=U,placeholder:i.placeholder||""},null,8,["modelValue","onUpdate:modelValue","placeholder"])),i.help?(o(),f("div",Kl,x(i.help),1)):b("",!0)]),_:2},1032,["label"]))),128))]),_:1})]),_:1},8,["modelValue","title"]),a(ul,{modelValue:G.value,"onUpdate:modelValue":n[8]||(n[8]=i=>G.value=i),title:`执行历史 — ${((De=Z.value)==null?void 0:De.config.name)??""}`,size:"55%"},{default:u(()=>[p("div",Yl,[p("div",Ql,[p("span",{class:ce(["q-live",{on:A.value}])},null,2),n[26]||(n[26]=p("span",{class:"live-title"},"实时输出",-1)),p("span",Gl,x(A.value?"运行中 · 自动刷新":"本次执行(已结束)"),1),X.value?b("",!0):(o(),f("span",{key:0,class:"live-jump",onClick:n[6]||(n[6]=i=>{X.value=!0,ue()})}," 回到底部 ↓ ")),a(e,{size:"small",link:"",onClick:n[7]||(n[7]=i=>{B.value="",$.value=""})},{default:u(()=>[...n[25]||(n[25]=[_("清屏",-1)])]),_:1})]),ve.value?(o(),V(tl,{key:0,title:ve.value,type:"warning","show-icon":"",closable:!1,class:"live-alert"},null,8,["title"])):b("",!0),B.value||$.value?(o(),f("pre",{key:1,ref_key:"liveEl",ref:re,class:"live-body",onScroll:we},[B.value?(o(),f("span",Zl,x(B.value),1)):b("",!0),$.value?(o(),f("span",Xl,x($.value),1)):b("",!0)],544)):(o(),f("div",et,x(A.value?"等待脚本输出…":"本次执行暂无输出"),1))]),p("div",{class:"hist-head"},[n[27]||(n[27]=p("span",{class:"hist-title"},"执行历史",-1)),p("span",{class:"hist-hint"},"仅保留最近 "+x(Oe)+" 条")]),a(nl,null,{default:u(()=>[(o(!0),f(C,null,q(z.value,i=>(o(),V(al,{key:i.id,timestamp:Q(i.startedAt),type:i.status==="completed"?"success":i.status==="failed"?"danger":"warning"},{default:u(()=>[p("div",lt,[a(se,{size:"small",type:$e[i.status==="completed"?"completed":i.status]??"info"},{default:u(()=>[_(x(ye[i.status]??i.status),1)]),_:2},1032,["type"]),p("span",tt,x(Ee(i.durationMs)),1)]),i.error?(o(),f("div",at,x(i.error),1)):b("",!0),i.stdout?(o(),f("details",nt,[n[28]||(n[28]=p("summary",null,"标准输出",-1)),p("pre",null,x(i.stdout),1)])):b("",!0),i.stderr?(o(),f("details",ut,[n[29]||(n[29]=p("summary",null,"错误输出",-1)),p("pre",null,x(i.stderr),1)])):b("",!0)]),_:2},1032,["timestamp","type"]))),128))]),_:1}),z.value.length?b("",!0):(o(),V(Ae,{key:0,description:"暂无执行记录"}))]),_:1},8,["modelValue","title"])])}}}),rt=Fe(ot,[["__scopeId","data-v-37d8bb63"]]);export{rt as default};
|