index2.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. <template>
  2. <div class="app-container">
  3. <el-row>
  4. <el-col :span="16">
  5. <el-form :model="queryParams" ref="queryRef" :inline="true" label-width="68px">
  6. <el-form-item label="任务名称">
  7. <el-input v-model="queryParams.jobName" style="width: 150px" placeholder="请输入任务名称"/>
  8. </el-form-item>
  9. <el-form-item label="任务状态">
  10. <el-select v-model="queryParams.jobStatus" class="noBorSel" placeholder="请选择任务状态"
  11. style="width: 120px;">
  12. <el-option label="启用" :value="0"/>
  13. <el-option label="禁用" :value="1"/>
  14. </el-select>
  15. </el-form-item>
  16. <el-form-item>
  17. <el-button type="primary" icon="Search" @click="getTable">查询</el-button>
  18. </el-form-item>
  19. </el-form>
  20. </el-col>
  21. <el-col :span="8" style="display: flex;justify-content: right;">
  22. <el-button plain type="primary" @click="showAdd" style="margin-left:auto;" :icon="Plus">新增
  23. </el-button>
  24. <el-button type="danger" @click="delAll" plain style="margin-left:1%;" :icon="Delete">删除
  25. </el-button>
  26. </el-col>
  27. </el-row>
  28. <el-table
  29. :data="tableData"
  30. :cell-style="{ paddingTop:'3px',paddingBottom:'3px' }"
  31. :header-cell-style="{height: heightAll*0.01+'px',}"
  32. @selection-change="handleSelectionChange"
  33. :row-style="{ fontSize: '16px',textAlign:'center'}"
  34. border
  35. :height="tableheight">
  36. <el-table-column type="selection" width="55"/>
  37. <el-table-column type="index" label="序号" width="80"></el-table-column>
  38. <el-table-column prop="jobName" label="任务名称" width="160" v-if="showTablepane.rw">
  39. <template #default="scope">
  40. <el-button type="primary" @click="showDe(scope.row)" text style="margin-left: 1%;">
  41. {{ scope.row.jobName }}
  42. </el-button>
  43. </template>
  44. </el-table-column>
  45. <el-table-column prop="groupName" label="组名称" width="160" v-if="showTablepane.zm"/>
  46. <el-table-column prop="executorInfo" label="执行器名称" width="160" v-if="showTablepane.zx"/>
  47. <el-table-column prop="ownerName" label="负责人" width="160" v-if="showTablepane.fz"/>
  48. <el-table-column prop="nextTriggerAt" label="触发时间" width="180" v-if="showTablepane.cf">
  49. </el-table-column>
  50. <el-table-column prop="jobStatus" label="状态" width="170" v-if="showTablepane.zt">
  51. <template #default="scope">
  52. <el-switch @change="changejobStatus(scope.row)" v-model="scope.row.jobStatus"/>
  53. </template>
  54. </el-table-column>
  55. <el-table-column prop="taskType" label="任务类型" width="170" v-if="showTablepane.rwl">
  56. <template #default="scope">
  57. <el-tag v-if="scope.row.taskType==1" type="success">集群</el-tag>
  58. <el-tag v-if="scope.row.taskType==2" type="info">广播</el-tag>
  59. <el-tag v-if="scope.row.taskType==3" type="warning">Sharding</el-tag>
  60. <el-tag v-if="scope.row.taskType==4" type="danger">Map</el-tag>
  61. <el-tag v-if="scope.row.taskType==5">MapReduce</el-tag>
  62. </template>
  63. </el-table-column>
  64. <el-table-column prop="triggerType" label="触发类型" width="170" v-if="showTablepane.cfl">
  65. <template #default="scope">
  66. <el-tag v-if="scope.row.triggerType==2">固定时间</el-tag>
  67. <el-tag v-if="scope.row.triggerType==3">CRON 表达式</el-tag>
  68. <el-tag v-if="scope.row.triggerType==99">工作流</el-tag>
  69. </template>
  70. </el-table-column>
  71. <el-table-column prop="retryInterval" label="间隔时长" width="170" v-if="showTablepane.jg"/>
  72. <el-table-column prop="blockStrategy" label="阻塞策略" width="170" v-if="showTablepane.zs">
  73. <template #default="scope">
  74. <el-tag v-if="scope.row.blockStrategy==1">丢弃</el-tag>
  75. <el-tag v-if="scope.row.blockStrategy==2">覆盖</el-tag>
  76. <el-tag v-if="scope.row.blockStrategy==3">并行</el-tag>
  77. </template>
  78. </el-table-column>
  79. <el-table-column prop="executorTimeout" label="超时时间(秒)" width="170" v-if="showTablepane.cs"/>
  80. <el-table-column prop="updateDt" label="更新时间" width="170" v-if="showTablepane.gx"/>
  81. <el-table-column prop="address" label="操作" width="222" fixed="right">
  82. <template #default="scope">
  83. <div style="display: flex;justify-content: space-between;width: 100%;">
  84. <el-button type="primary" @click="showEdit(scope.row)" text style="margin-left: 1%;">编辑
  85. </el-button>
  86. <el-button @click="snaliTrigger(scope.row)" type="primary" text style="margin-left: 1%;">
  87. 执行
  88. </el-button>
  89. <el-button @click="delRow(scope.row)" type="danger" text style="margin-left: 1%;">删除
  90. </el-button>
  91. </div>
  92. </template>
  93. </el-table-column>
  94. </el-table>
  95. </div>
  96. <el-dialog :title="title" @close="clearForm" v-model="dialogVisible" title="" width="60%" destroy-on-close>
  97. <el-form style="margin-top: 0;width: 98%;" :model="formJi" label-position="right" ref="formRefJi"
  98. label-width="120px" :rules="rulesJi">
  99. <el-row :gutter="24">
  100. <el-col :span="8">
  101. <el-form-item label="任务名称:" prop="jobName" style="">
  102. <div style="display: flex;width: 100%;justify-content: space-between;">
  103. <el-input v-model="formJi.jobName" style="width: 100%;"/>
  104. </div>
  105. </el-form-item>
  106. </el-col>
  107. <el-col :span="8">
  108. <el-form-item label="负责人:" prop="" style="">
  109. <div style="display: flex;width: 100%;justify-content: space-between;">
  110. <el-input v-model="formJi.ownerName" style="width: 100%;"/>
  111. </div>
  112. </el-form-item>
  113. </el-col>
  114. </el-row>
  115. <el-row :gutter="48">
  116. <el-col :span="15">
  117. <!-- <el-form-item label="标签:" prop="" style="">
  118. <div
  119. v-if="parTag.length==0"
  120. @click='addTag'
  121. style="
  122. cursor: pointer;
  123. display: flex;
  124. justify-content: center;
  125. align-items: center;
  126. width: 200px;
  127. height: 30px;
  128. border: 0.5px dashed #c8c9cc;
  129. border-radius: 8px;
  130. position: relative;
  131. "
  132. >
  133. + &nbsp;添加
  134. </div>
  135. <div v-if="parTag.length!=0" v-for="(item,index) in parTag">
  136. <div style="display: flex;align-items: center;margin-top: 3%;" :class="{ 'no-margin-top': index === 0 }">
  137. <el-input v-model="item.key" style="width: 50%;" resize="none" placeholder="key"/>
  138. <div style="margin-left: 1%;">:</div>
  139. <el-input v-model="item.value" style="width: 50%;margin-left: 1%;" resize="none" placeholder="value"/>
  140. <el-icon @click="delTag(index)" style="margin-left: 3%;color: red;cursor: pointer;"><Minus /></el-icon>
  141. <el-icon @click="addTag" style="margin-left: 3%;color: #337ecc;cursor: pointer;"><Plus /></el-icon>
  142. </div>
  143. </div>
  144. </el-form-item> -->
  145. </el-col>
  146. </el-row>
  147. <el-row :gutter="48">
  148. <el-col :span="8">
  149. <el-form-item label="状态:" prop="jobStatus">
  150. <el-radio-group :disabled="!isAddTa" v-model="formJi.jobStatus" class="custom-radio-group"
  151. style="width: 100%;margin-top: -1%;">
  152. <el-radio :label="1">启用</el-radio>
  153. <el-radio :label="0">禁用</el-radio>
  154. </el-radio-group>
  155. </el-form-item>
  156. </el-col>
  157. </el-row>
  158. <el-row :gutter="48">
  159. <el-col :span="8">
  160. <el-form-item label="任务类型:" prop="taskType">
  161. <el-select
  162. v-model="formJi.taskType"
  163. class="noBorSel"
  164. placeholder=""
  165. style="width: 100%;margin-left: 0;"
  166. >
  167. <el-option
  168. v-for="item in optionsTaskType"
  169. :key="item.value"
  170. :label="item.label"
  171. :value="item.value"
  172. />
  173. </el-select>
  174. </el-form-item>
  175. </el-col>
  176. </el-row>
  177. <div style="margin-top: 0;">
  178. <el-form-item label="任务配置:">
  179. <args-str v-model="formJi.argsStr"></args-str>
  180. </el-form-item>
  181. <el-row :gutter="48">
  182. <el-col :span="8">
  183. <el-form-item label="路由策略:" prop="routeKey">
  184. <el-select
  185. v-model="formJi.routeKey"
  186. class="noBorSel"
  187. placeholder=""
  188. style="width: 100%;margin-left: 0;"
  189. >
  190. <el-option label="Hash" :value="1"/>
  191. <el-option label="随机" :value="2"/>
  192. <el-option label="LRU" :value="3"/>
  193. <el-option label="轮询" :value="4"/>
  194. <el-option label="匹配第一个" :value="5"/>
  195. <el-option label="匹配最后一个" :value="6"/>
  196. </el-select>
  197. </el-form-item>
  198. </el-col>
  199. <el-col :span="8">
  200. <el-form-item label="阻塞策略:" prop="blockStrategy">
  201. <el-select
  202. v-model="formJi.blockStrategy"
  203. class="noBorSel"
  204. placeholder=""
  205. style="width: 100%;margin-left: 0;"
  206. >
  207. <el-option label="丢弃" :value="1"/>
  208. <el-option label="覆盖" :value="2"/>
  209. <el-option label="并行" :value="3"/>
  210. </el-select>
  211. </el-form-item>
  212. </el-col>
  213. </el-row>
  214. <el-row :gutter="48">
  215. <el-col :span="8">
  216. <el-form-item label="触发类型:" prop="triggerType">
  217. <el-select
  218. v-model="formJi.triggerType"
  219. class="noBorSel"
  220. placeholder=""
  221. style="width: 100%;margin-left: 0;"
  222. >
  223. <el-option label="固定时间" :value="2"/>
  224. <el-option label="CRON 表达式" :value="3"/>
  225. <el-option label="工作流" :value="99"/>
  226. </el-select>
  227. </el-form-item>
  228. </el-col>
  229. <el-col :span="8">
  230. <el-form-item label="间隔时长:" prop="triggerInterval">
  231. <el-input v-model="formJi.triggerInterval" placeholder="请选择调度周期">
  232. <template #append>
  233. <el-button type="primary" @click="handleShowCron" style="background-color: #2666fb; color: #fff">
  234. 配置
  235. <i class="el-icon-time el-icon--right"></i>
  236. </el-button>
  237. </template>
  238. </el-input>
  239. </el-form-item>
  240. </el-col>
  241. </el-row>
  242. <el-row :gutter="48">
  243. <el-col :span="8">
  244. <el-form-item label="超时时间(秒):" prop="executorTimeout">
  245. <el-input-number
  246. v-model="formJi.executorTimeout"
  247. style="width: 100%;"
  248. class="mx-4"
  249. :min="1"
  250. :max="10"
  251. controls-position="right"
  252. />
  253. </el-form-item>
  254. </el-col>
  255. <el-col :span="8">
  256. <el-form-item label="最大重试次数:" prop="maxRetryTimes">
  257. <el-input-number
  258. v-model="formJi.maxRetryTimes"
  259. style="width: 100%;"
  260. class="mx-4"
  261. :min="1"
  262. :max="10"
  263. controls-position="right"
  264. />
  265. </el-form-item>
  266. </el-col>
  267. </el-row>
  268. <el-row :gutter="48">
  269. <el-col :span="8">
  270. <el-form-item label="重试间隔:" prop="retryInterval">
  271. <el-input-number
  272. v-model="formJi.retryInterval"
  273. style="width: 100%;"
  274. class="mx-4"
  275. :min="1"
  276. :max="10"
  277. controls-position="right"
  278. />
  279. </el-form-item>
  280. </el-col>
  281. </el-row>
  282. <el-form-item label="描述:">
  283. <el-input v-model="formJi.description" style="width: 75%;" placeholder="" type="textarea" :row="2"
  284. resize="none"/>
  285. </el-form-item>
  286. </div>
  287. </el-form>
  288. <template #footer>
  289. <span class="dialog-footer">
  290. <el-button @click="dialogVisible = false">取消</el-button>
  291. <el-button v-if="isAddTa" type="primary" @click="addTa">
  292. 提交
  293. </el-button>
  294. <el-button v-if="!isAddTa" type="primary" @click="saveEditTa">
  295. 提交
  296. </el-button>
  297. </span>
  298. </template>
  299. </el-dialog>
  300. <el-dialog @close="clearFromTree" v-model="dialogVisibleTree" title="" width="55%" destroy-on-close>
  301. <el-descriptions
  302. class="margin-top"
  303. :title="titleDe"
  304. style="padding-top: 2%;"
  305. :column="3"
  306. :size="size"
  307. border
  308. >
  309. <el-descriptions-item>
  310. <template #label>
  311. <div class="cell-item">
  312. 任务名称
  313. </div>
  314. </template>
  315. {{ formJi.jobName }}
  316. </el-descriptions-item>
  317. <el-descriptions-item>
  318. <template #label>
  319. <div class="cell-item">
  320. 组名称
  321. </div>
  322. </template>
  323. {{ formJi.groupName }}
  324. </el-descriptions-item>
  325. <el-descriptions-item>
  326. <template #label>
  327. <div class="cell-item">
  328. 负责人
  329. </div>
  330. </template>
  331. {{ formJi.ownerName }}
  332. </el-descriptions-item>
  333. <el-descriptions-item>
  334. <template #label>
  335. <div class="cell-item">
  336. 状态
  337. </div>
  338. </template>
  339. <el-tag>{{ formJi.jobStatus }}</el-tag>
  340. </el-descriptions-item>
  341. <el-descriptions-item>
  342. <template #label>
  343. <div class="cell-item">
  344. 任务类型
  345. </div>
  346. </template>
  347. {{ formJi.taskType }}
  348. </el-descriptions-item>
  349. <el-descriptions-item>
  350. <template #label>
  351. <div class="cell-item">
  352. 执行器名称
  353. </div>
  354. </template>
  355. {{ formJi.executorInfo }}
  356. </el-descriptions-item>
  357. <el-descriptions-item>
  358. <template #label>
  359. <div class="cell-item">
  360. 方法参数
  361. </div>
  362. </template>
  363. {{ formJi.argsStr }}
  364. </el-descriptions-item>
  365. <el-descriptions-item>
  366. <template #label>
  367. <div class="cell-item">
  368. 路由策略
  369. </div>
  370. </template>
  371. {{ formJi.routeKey }}
  372. </el-descriptions-item>
  373. <el-descriptions-item>
  374. <template #label>
  375. <div class="cell-item">
  376. 阻塞策略
  377. </div>
  378. </template>
  379. {{ formJi.blockStrategy }}
  380. </el-descriptions-item>
  381. <el-descriptions-item>
  382. <template #label>
  383. <div class="cell-item">
  384. 触发类型
  385. </div>
  386. </template>
  387. {{ formJi.triggerType }}
  388. </el-descriptions-item>
  389. <el-descriptions-item>
  390. <template #label>
  391. <div class="cell-item">
  392. 间隔时长
  393. </div>
  394. </template>
  395. {{ formJi.triggerInterval }}
  396. </el-descriptions-item>
  397. <el-descriptions-item>
  398. <template #label>
  399. <div class="cell-item">
  400. 超时时间(秒)
  401. </div>
  402. </template>
  403. {{ formJi.executorTimeout }}
  404. </el-descriptions-item>
  405. <el-descriptions-item>
  406. <template #label>
  407. <div class="cell-item">
  408. 最大重试次数
  409. </div>
  410. </template>
  411. {{ formJi.maxRetryTimes }}
  412. </el-descriptions-item>
  413. <el-descriptions-item>
  414. <template #label>
  415. <div class="cell-item">
  416. 重试间隔
  417. </div>
  418. </template>
  419. {{ formJi.retryInterval }}
  420. </el-descriptions-item>
  421. <el-descriptions-item>
  422. <template #label>
  423. <div class="cell-item">
  424. 描述:
  425. </div>
  426. </template>
  427. {{ formJi.description }}
  428. </el-descriptions-item>
  429. </el-descriptions>
  430. <template #footer>
  431. <span class="dialog-footer">
  432. <el-button type="primary" @click="dialogVisibleTree = false">确定</el-button>
  433. </span>
  434. </template>
  435. </el-dialog>
  436. <el-dialog title="Cron表达式生成器" v-model="openCron" class="dialog" append-to-body destroy-on-close>
  437. <crontab ref="crontabRef" @hide="openCron = false" @fill="crontabFill" :expression="expression"></crontab>
  438. </el-dialog>
  439. </template>
  440. <script setup>
  441. import {Delete, Plus} from '@element-plus/icons-vue'
  442. import {onMounted, reactive, ref} from 'vue'
  443. import {addSnail, delSnamil, snailDe, snailEdit, snailList, snailSta, snailTri} from "@/api/service/timing";
  444. import ArgsStr from "@/views/dpp/task/integratioTask/argsStr.vue";
  445. import Crontab from "@/components/Crontab/index.vue";
  446. import {copyObj} from "codemirror/src/util/misc.js";
  447. const queryParams = ref({
  448. jobName: '',
  449. jobStatus: null,
  450. })
  451. const {proxy} = getCurrentInstance();
  452. const title = ref([])
  453. const total = ref(1)
  454. const tableData = ref([])
  455. const tableheight = window.innerHeight * 0.8
  456. const heightAll = window.innerHeight
  457. const dialogVisible = ref(false)
  458. const dialogVisibleTree = ref(false)
  459. const isAddTa = ref(false)
  460. const titleDe = ref('')
  461. const optionsTaskType = ref([
  462. {
  463. label: '集群',
  464. value: 1
  465. },
  466. {
  467. label: '广播',
  468. value: 2
  469. },
  470. {
  471. label: 'Sharding',
  472. value: 3
  473. },
  474. {
  475. label: 'Map',
  476. value: 4
  477. },
  478. {
  479. label: 'MapReduce',
  480. value: 5
  481. },
  482. ])
  483. const showTablepane = ref({
  484. rw: true,
  485. zm: true,
  486. zx: true,
  487. fz: true,
  488. bq: true,
  489. cf: true,
  490. zt: true,
  491. rwl: true,
  492. cfl: true,
  493. jg: true,
  494. zs: true,
  495. cs: true,
  496. gx: true,
  497. })
  498. const formJi = ref({
  499. jobName: '',
  500. groupName: '',
  501. jobStatus: '',
  502. taskType: '',
  503. executorInfo: '',
  504. executorInfoTy: '',
  505. type: '',
  506. mdContact: '',
  507. mdUnit: '',
  508. devUnit: '',
  509. devContact: '',
  510. deployDir: '',
  511. deployIp: '',
  512. deployPort: '',
  513. mirrorImageUrl: '',
  514. mdRunCmd: '',
  515. envOs: '',
  516. envDisk: '',
  517. envGpuMem: '11',
  518. evnArmX86: '',
  519. envCpuNum: '',
  520. envGpuType: '',
  521. envGpuNum: '2',
  522. envMem: '',
  523. mdInNote: '',
  524. mdOutNote: '',
  525. triggerInterval: ''
  526. });
  527. const selectedRows = ref([])
  528. const rulesJi = reactive({
  529. jobName: [{required: true, message: '必填', trigger: 'blur'}],
  530. groupName: [{required: true, message: '必填', trigger: 'blur'}],
  531. taskType: [{required: true, message: '必填', trigger: 'blur'}],
  532. jobStatus: [{required: true, message: '必填', trigger: 'blur'}],
  533. executorInfo: [{required: true, message: '必填', trigger: 'blur'}],
  534. routeKey: [{required: true, message: '可选', trigger: 'blur'}],
  535. blockStrategy: [{required: true, message: '必填', trigger: 'blur'}],
  536. triggerInterval: [{required: true, message: '必填', trigger: 'blur'}],
  537. executorTimeout: [{required: true, message: '必填', trigger: 'blur'}],
  538. maxRetryTimes: [{required: true, message: '必填', trigger: 'blur'}],
  539. retryInterval: [{required: true, message: '必填', trigger: 'blur'}],
  540. triggerType: [{required: true, message: '必填', trigger: 'blur'}],
  541. });
  542. const formRefJi = ref();
  543. const formTree = ref({
  544. itemName: '',
  545. catePid: '',
  546. itemNo: '',
  547. itemNotes: ''
  548. });
  549. let openCron = ref(false);
  550. const expression = ref("");
  551. const handleSelectionChange = (selection) => {
  552. selectedRows.value = selection;
  553. };
  554. function snaliTrigger(row) {
  555. var par = {
  556. jobId: row.id,
  557. taskType: row.taskType
  558. }
  559. snailTri(par).then(res => {
  560. if (res.code === 200) {
  561. proxy.$modal.msgSuccess(res.msg);
  562. }
  563. })
  564. }
  565. function showCode() {
  566. Object.keys(rulesJi).forEach(key => {
  567. delete rulesJi[key];
  568. });
  569. if (formJi.value.executorInfoTy === '自定义执行器') {
  570. Object.assign(rulesJi, {
  571. jobName: [{required: true, message: '必填', trigger: 'blur'}],
  572. groupName: [{required: true, message: '必填', trigger: 'blur'}],
  573. taskType: [{required: true, message: '必填', trigger: 'blur'}],
  574. jobStatus: [{required: true, message: '必填', trigger: 'blur'}],
  575. executorInfo: [{required: true, message: '必填', trigger: 'blur'}],
  576. routeKey: [{required: true, message: '可选', trigger: 'blur'}],
  577. blockStrategy: [{required: true, message: '必填', trigger: 'blur'}],
  578. triggerInterval: [{required: true, message: '必填', trigger: 'blur'}],
  579. executorTimeout: [{required: true, message: '必填', trigger: 'blur'}],
  580. maxRetryTimes: [{required: true, message: '必填', trigger: 'blur'}],
  581. retryInterval: [{required: true, message: '必填', trigger: 'blur'}],
  582. triggerType: [{required: true, message: '必填', trigger: 'blur'}],
  583. });
  584. }
  585. if (formJi.value.executorInfoTy === '内置执行器') {
  586. Object.assign(rulesJi, {
  587. jobName: [{required: true, message: '必填', trigger: 'blur'}],
  588. groupName: [{required: true, message: '必填', trigger: 'blur'}],
  589. taskType: [{required: true, message: '必填', trigger: 'blur'}],
  590. jobStatus: [{required: true, message: '必填', trigger: 'blur'}],
  591. executorInfo: [{required: true, message: '必填', trigger: 'blur'}],
  592. routeKey: [{required: true, message: '可选', trigger: 'blur'}],
  593. blockStrategy: [{required: true, message: '必填', trigger: 'blur'}],
  594. triggerInterval: [{required: true, message: '必填', trigger: 'blur'}],
  595. executorTimeout: [{required: true, message: '必填', trigger: 'blur'}],
  596. maxRetryTimes: [{required: true, message: '必填', trigger: 'blur'}],
  597. retryInterval: [{required: true, message: '必填', trigger: 'blur'}],
  598. triggerType: [{required: true, message: '必填', trigger: 'blur'}],
  599. });
  600. }
  601. }
  602. function delAll() {
  603. var parDel = ''
  604. selectedRows.value.forEach(item => {
  605. parDel = parDel + item.id + ','
  606. })
  607. parDel = parDel.slice(0, -1)
  608. proxy.$modal.confirm('是否确认删除?').then(function () {
  609. var par = {
  610. jobIds: parDel
  611. }
  612. return delSnamil(par);
  613. }).then(() => {
  614. getTable();
  615. proxy.$modal.msgSuccess("删除成功");
  616. }).catch(() => {
  617. });
  618. }
  619. function showDe(row) {
  620. dialogVisibleTree.value = true
  621. var par = {
  622. jobId: row.id
  623. }
  624. snailDe(par).then(res => {
  625. formJi.value = res.data
  626. if (formJi.value.jobStatus === 0) {
  627. formJi.value.jobStatus = '启用'
  628. }
  629. if (formJi.value.jobStatus === 1) {
  630. formJi.value.jobStatus = '关闭'
  631. }
  632. })
  633. }
  634. async function changejobStatus(row) {
  635. var par = {
  636. jobId: row.id,
  637. status: row.jobStatus === true ? 1 : 0
  638. }
  639. await snailSta(par).then(res => {
  640. formJi.value = res
  641. if (res.code === 200) {
  642. proxy.$modal.msgSuccess("修改成功");
  643. }
  644. })
  645. }
  646. function clearForm() {
  647. formJi.value = {}
  648. }
  649. function formatTimestamp(ms) {
  650. const date = new Date(ms);
  651. const year = date.getFullYear();
  652. const month = String(date.getMonth() + 1).padStart(2, '0'); // 补零
  653. const day = String(date.getDate()).padStart(2, '0'); // 补零
  654. return `${year}年${month}月${day}日`;
  655. }
  656. function getTable() {
  657. queryParams.value.executorInfo = 'cleanDataJob'
  658. snailList(queryParams.value).then(res => {
  659. tableData.value = res.rows
  660. tableData.value.forEach(item => {
  661. if (item.jobStatus === 0) {
  662. item.jobStatus = false
  663. }
  664. if (item.jobStatus === 1) {
  665. item.jobStatus = true
  666. }
  667. item.nextTriggerAt = formatTimestamp(item.nextTriggerAt)
  668. })
  669. total.value = res.total
  670. })
  671. }
  672. function showAdd() {
  673. isAddTa.value = true
  674. title.value = '新增'
  675. dialogVisible.value = true
  676. formJi.value = {
  677. taskType: 1,
  678. jobStatus: 1,
  679. routeKey: 4,
  680. blockStrategy: 1,
  681. triggerType: 3,
  682. executorTimeout: 60,
  683. maxRetryTimes: 3,
  684. retryInterval: 1,
  685. }
  686. }
  687. function showEdit(row) {
  688. isAddTa.value = false
  689. title.value = '编辑'
  690. dialogVisible.value = true
  691. var par = {
  692. jobId: row.id
  693. }
  694. snailDe(par).then(res => {
  695. formJi.value = res.data
  696. })
  697. }
  698. function clearFromTree() {
  699. formTree.value = {
  700. itemName: '',
  701. catePid: '',
  702. itemNo: '',
  703. itemNotes: ''
  704. }
  705. }
  706. function addTa() {
  707. formRefJi.value.validate(async (valid) => {
  708. if (valid) {
  709. formJi.value.executorInfo = 'cleanDataJob'
  710. formJi.value.argsStrMap = JSON.parse(formJi.value.argsStr)
  711. await addSnail(formJi.value).then(res => {
  712. if (res.code === 200) {
  713. proxy.$modal.msgSuccess("新增成功");
  714. getTable()
  715. dialogVisible.value = false
  716. }
  717. })
  718. }
  719. });
  720. }
  721. function saveEditTa() {
  722. formJi.value.executorInfo = 'cleanDataJob'
  723. formJi.value.argsStrMap = JSON.parse(formJi.value.argsStr)
  724. snailEdit(formJi.value).then(res => {
  725. if (res.code === 200) {
  726. proxy.$modal.msgSuccess("修改成功");
  727. dialogVisible.value = false
  728. getTable()
  729. }
  730. })
  731. }
  732. function delRow(row) {
  733. proxy.$modal.confirm('是否确认删除?').then(function () {
  734. var par = {
  735. jobIds: row.id
  736. }
  737. return delSnamil(par);
  738. }).then(() => {
  739. getTable();
  740. proxy.$modal.msgSuccess("删除成功");
  741. }).catch(() => {
  742. });
  743. }
  744. /** 调度周期按钮操作 */
  745. function handleShowCron() {
  746. expression.value = formJi.value.triggerInterval;
  747. openCron.value = true;
  748. }
  749. /** 确定后回传值 */
  750. function crontabFill(value) {
  751. formJi.value.triggerInterval = value;
  752. }
  753. onMounted(() => {
  754. getTable()
  755. })
  756. </script>
  757. <style scoped>
  758. .no-margin-top {
  759. margin-top: 0 !important;
  760. }
  761. .drag-handle {
  762. cursor: move;
  763. }
  764. .ghost {
  765. opacity: 0.5;
  766. background: #c8ebfb;
  767. }
  768. /* 防止文字选中 */
  769. :deep(.el-table__row) {
  770. user-select: none;
  771. -webkit-user-select: none;
  772. }
  773. </style>
  774. <style scoped lang="scss">
  775. .el-table .el-table__row td {
  776. height: 60px !important; /* 行高 */
  777. }
  778. .custom-tree-node {
  779. display: flex; /* 启用 Flex 布局 */
  780. align-items: center; /* 垂直居中 */
  781. gap: 8px; /* 图标与文字间距 */
  782. }
  783. .custom-tree-node {
  784. flex: 1;
  785. display: flex;
  786. align-items: center;
  787. justify-content: space-between;
  788. font-size: 14px;
  789. padding-right: 8px;
  790. }
  791. </style>