index.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. <script setup lang="ts" name="Job">
  2. import apis from "@a"
  3. import message from "@@/utils/message"
  4. import dayjs from "dayjs"
  5. const jobTypeOptions = computed(() => {
  6. return [
  7. { label: "接口", value: "1" },
  8. { label: "函数", value: "2" }
  9. ]
  10. })
  11. const misfirePolicyOptions = computed(() => {
  12. return [
  13. { label: "立即执行", value: "1" },
  14. { label: "执行一次", value: "2" },
  15. { label: "放弃执行", value: "3" }
  16. ]
  17. })
  18. const concurrentOptions = computed(() => {
  19. return [
  20. { label: "允许", value: "2" },
  21. { label: "禁止", value: "1" }
  22. ]
  23. })
  24. const jobKeysOptions = ref<any[]>([])
  25. const tableRef = ref()
  26. const modalRef = ref()
  27. const opts = reactive<any>({
  28. columns: [
  29. { field: "jobId", name: "编码", width: 100, visible: false, isSort: false, tooltip: true },
  30. { field: "jobName", name: "名称", width: "auto", isSort: true, visible: true },
  31. { field: "jobGroup", name: "任务分组", width: 100, isSort: true, visible: true },
  32. { field: "cronExpression", name: "Cron表达式", width: "auto", isSort: false, visible: true },
  33. { field: "invokeTarget", name: "调用目标", width: "auto", isSort: false, visible: true },
  34. { field: "status", name: "状态", width: 100, isSort: true, visible: true },
  35. { field: "createdAt", name: "创建时间", width: 185, isSort: true, visible: true },
  36. { field: "actions", name: `操作`, width: 150 }
  37. ],
  38. queryParams: {
  39. jobName: undefined,
  40. jobType: undefined,
  41. invokeTarget: undefined,
  42. status: undefined
  43. },
  44. searchFormItems: [
  45. {
  46. field: "jobName",
  47. label: "名称",
  48. class: "w-100",
  49. component: "I",
  50. listeners: {
  51. keyup: (e: KeyboardEvent) => {
  52. if (e.code == "Enter") {
  53. handleQuery()
  54. }
  55. }
  56. }
  57. },
  58. {
  59. field: "jobGroup",
  60. label: "任务分组",
  61. class: "w-100",
  62. component: "Dict",
  63. props: {
  64. showAll: true,
  65. type: "select",
  66. clearable: true,
  67. placeholder: "请选择任务分组",
  68. dictType: "sys_job_group"
  69. }
  70. },
  71. {
  72. field: "jobType",
  73. label: "调用类型",
  74. class: "w-100",
  75. component: "VS",
  76. placeholder: "请选择调用类型",
  77. data: () => jobTypeOptions.value,
  78. props: {
  79. showAll: true,
  80. valueIsNumber: true,
  81. type: "select",
  82. clearable: true
  83. }
  84. },
  85. {
  86. field: "invokeTarget",
  87. label: "调用目标",
  88. class: "w-100",
  89. component: "I",
  90. listeners: {
  91. keyup: (e: KeyboardEvent) => {
  92. if (e.code == "Enter") {
  93. handleQuery()
  94. }
  95. }
  96. }
  97. },
  98. {
  99. field: "status",
  100. label: "状态",
  101. class: "w-100",
  102. component: "Dict",
  103. props: {
  104. showAll: true,
  105. type: "select",
  106. clearable: true,
  107. valueIsNumber: true,
  108. placeholder: "请选择状态",
  109. dictType: "sys_job_status"
  110. }
  111. }
  112. ] as any,
  113. permission: "schedule:job",
  114. handleFuns: {},
  115. customBtns: [],
  116. tableListFun: apis.schedule.jobApi.listJob,
  117. getEntityFun: apis.schedule.jobApi.getJob,
  118. deleteEntityFun: apis.schedule.jobApi.delJob,
  119. formItems: [
  120. {
  121. field: "jobName",
  122. label: "名称",
  123. class: "w-100",
  124. component: "I",
  125. required: true
  126. },
  127. {
  128. field: "jobGroup",
  129. label: "任务分组",
  130. class: "w-100",
  131. required: true,
  132. component: "Dict",
  133. props: {
  134. type: "select",
  135. clearable: true,
  136. placeholder: "请选择任务分组",
  137. dictType: "sys_job_group"
  138. }
  139. },
  140. {
  141. field: "jobType",
  142. label: "调用类型",
  143. class: "w-100",
  144. required: true,
  145. component: "VS",
  146. placeholder: "请选择调用类型",
  147. data: () => jobTypeOptions.value,
  148. props: {
  149. type: "radio",
  150. valueIsNumber: true,
  151. clearable: true
  152. },
  153. listeners: {
  154. change: () => {
  155. form.value.invokeTarget = ""
  156. }
  157. }
  158. },
  159. {
  160. show: () => form.value.jobType == 1,
  161. field: "invokeTarget",
  162. label: "调用目标",
  163. class: "w-100",
  164. component: "I",
  165. required: true,
  166. placeholder: "请填写调用接口"
  167. },
  168. {
  169. show: () => form.value.jobType == 2,
  170. field: "invokeTarget",
  171. label: "调用目标",
  172. class: "w-100",
  173. component: "VS",
  174. required: true,
  175. data: () => jobKeysOptions.value,
  176. props: {
  177. type: "select",
  178. clearable: true,
  179. placeholder: "请选择调用函数"
  180. }
  181. },
  182. {
  183. field: "args",
  184. label: "目标参数",
  185. class: "w-100",
  186. component: "I",
  187. required: false
  188. },
  189. {
  190. field: "cronExpression",
  191. label: "Cron表达式",
  192. class: "w-100",
  193. component: "I",
  194. required: true
  195. },
  196. {
  197. field: "misfirePolicy",
  198. label: "执行策略",
  199. class: "w-100",
  200. required: false,
  201. component: "VS",
  202. placeholder: "请选择执行策略",
  203. data: () => misfirePolicyOptions.value,
  204. props: {
  205. type: "radio",
  206. valueIsNumber: true,
  207. clearable: true
  208. }
  209. },
  210. {
  211. field: "concurrent",
  212. label: "是否并发",
  213. class: "w-100",
  214. required: false,
  215. component: "VS",
  216. placeholder: "请选择是否并发",
  217. data: () => concurrentOptions.value,
  218. props: {
  219. type: "radio",
  220. valueIsNumber: true,
  221. clearable: true
  222. }
  223. }
  224. ] as any,
  225. resetForm: () => {
  226. form.value = emptyFormData.value
  227. },
  228. emptyFormData: {
  229. jobId: undefined,
  230. jobName: undefined,
  231. jobGroup: "DEFAULT",
  232. jobType: 1,
  233. cronExpression: undefined,
  234. invokeTarget: undefined,
  235. args: undefined,
  236. misfirePolicy: 1,
  237. concurrent: undefined,
  238. status: 2
  239. }
  240. })
  241. const { emptyFormData } = toRefs(opts)
  242. const queryParams = ref(Object.assign({}, opts.queryParams))
  243. const form = ref<any>(emptyFormData.value)
  244. /** 修改按钮操作 */
  245. function handleUpdate(row: any) {
  246. tableRef.value.defaultHandleFuns.handleUpdate("", row)
  247. }
  248. /** 删除按钮操作 */
  249. function handleDelete(rows: any[]) {
  250. tableRef.value.defaultHandleFuns.handleDelete("", rows)
  251. }
  252. /** 提交按钮 */
  253. function submitForm() {
  254. if (form.value.jobId != undefined) {
  255. apis.schedule.jobApi.updateJob(form.value).then(() => {
  256. message.msgSuccess("修改成功")
  257. handleQuery()
  258. })
  259. } else {
  260. apis.schedule.jobApi.addJob(form.value).then(() => {
  261. message.msgSuccess("新增成功")
  262. handleQuery()
  263. })
  264. }
  265. }
  266. /** 查询按钮 */
  267. function handleQuery() {
  268. tableRef.value?.search()
  269. }
  270. /** 查询重置按钮 */
  271. function resetQuery() {
  272. queryParams.value = opts.queryParams
  273. }
  274. function handleStart(row: any) {
  275. message
  276. .confirm("是否确认启动任务?", "提示", {
  277. confirmButtonText: "确定",
  278. cancelButtonText: "取消",
  279. type: "warning"
  280. })
  281. .then(() => {
  282. apis.schedule.jobApi.startJob(row.jobId).then(() => {
  283. message.msgSuccess("启动成功")
  284. handleQuery()
  285. })
  286. })
  287. }
  288. function handleStop(row: any) {
  289. message
  290. .confirm("是否确认停止任务?", "提示", {
  291. confirmButtonText: "确定",
  292. cancelButtonText: "取消",
  293. type: "warning"
  294. })
  295. .then(() => {
  296. apis.schedule.jobApi.stopJob(row.jobId).then(() => {
  297. message.msgSuccess("停止成功")
  298. handleQuery()
  299. })
  300. })
  301. }
  302. function init() {
  303. apis.schedule.jobApi.getJobKeys().then((res: any) => {
  304. if (res.data) {
  305. jobKeysOptions.value = Object.keys(res.data).map((key: any) => {
  306. return {
  307. value: key,
  308. label: res.data[key]
  309. }
  310. })
  311. }
  312. })
  313. }
  314. onMounted(() => setTimeout(init, 100))
  315. </script>
  316. <template>
  317. <div class="app-container">
  318. <VbDataTable
  319. ref="tableRef"
  320. :handle-perm="opts.permission"
  321. :handle-funs="opts.handleFuns"
  322. :search-form-items="opts.searchFormItems"
  323. :columns="opts.columns"
  324. :custom-btns="opts.customBtns"
  325. :remote-fun="opts.tableListFun"
  326. :get-entity-fun="opts.getEntityFun"
  327. :delete-entity-fun="opts.deleteEntityFun"
  328. sortField="createdAt"
  329. sort-order="desc"
  330. :modal="modalRef"
  331. :reset-form-fun="opts.resetForm"
  332. v-model:form-data="form"
  333. :query-params="queryParams"
  334. :check-multiple="true"
  335. :has-checkbox="true"
  336. :reset-search-form-fun="resetQuery"
  337. :custom-search-fun="handleQuery">
  338. <template #jobGroup="{ row }">
  339. <DictTag :value="row.jobGroup" type="sys_job_group"></DictTag>
  340. </template>
  341. <template #status="{ row }">
  342. <DictTag :value="row.status" valueIsNumber type="sys_job_status"></DictTag>
  343. </template>
  344. <template #createdAt="{ row }">
  345. <span>{{ dayjs(row.createdAt).format("YYYY-MM-DD HH:mm:ss") }}</span>
  346. </template>
  347. <template #actions="{ row }">
  348. <vb-tooltip content="修改" placement="top">
  349. <el-button link type="primary" @click="handleUpdate(row)">
  350. <template #icon>
  351. <VbIcon icon-name="notepad-edit" icon-type="duotone" class="fs-3"></VbIcon>
  352. </template>
  353. </el-button>
  354. </vb-tooltip>
  355. <vb-tooltip v-if="row.status == 1" content="启动任务" placement="top">
  356. <el-button link type="success" @click="handleStart(row)">
  357. <template #icon>
  358. <VbIcon icon-name="right-square" icon-type="duotone" class="fs-3"></VbIcon>
  359. </template>
  360. </el-button>
  361. </vb-tooltip>
  362. <vb-tooltip v-if="row.status == 2" content="停止任务" placement="top">
  363. <el-button link type="danger" @click="handleStop(row)">
  364. <template #icon>
  365. <VbIcon icon-name="cross-square" icon-type="duotone" class="fs-3"></VbIcon>
  366. </template>
  367. </el-button>
  368. </vb-tooltip>
  369. <vb-tooltip content="删除" placement="top">
  370. <el-button link type="primary" @click="handleDelete([row])">
  371. <template #icon>
  372. <VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
  373. </template>
  374. </el-button>
  375. </vb-tooltip>
  376. </template>
  377. </VbDataTable>
  378. <VbModal
  379. v-model:modal="modalRef"
  380. :title="opts.modalTitle"
  381. :form-items="opts.formItems as any"
  382. :form-data="form"
  383. @confirm="submitForm"
  384. append-to-body></VbModal>
  385. </div>
  386. </template>