From 426063dd234a76640ec6035417d06c4401b79af7 Mon Sep 17 00:00:00 2001 From: byteblogs168 <598092184@qq.com> Date: Fri, 29 Dec 2023 23:27:23 +0800 Subject: [PATCH] =?UTF-8?q?feat:=202.6.0=201.=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=8A=9F=E8=83=BD=202.=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=BC=80=E5=85=B3=E5=B7=A5=E4=BD=9C=E6=B5=81=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=203.=20=E6=96=B0=E5=A2=9E=E5=A4=8D=E5=88=B6=E6=8C=89=E9=92=AE?= =?UTF-8?q?=E5=BE=85=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/controller/WorkflowController.java | 14 ++++- .../response/WorkflowDetailResponseVO.java | 5 ++ .../server/web/service/WorkflowService.java | 4 ++ .../web/service/impl/WorkflowServiceImpl.java | 59 +++++++++++++------ frontend/src/api/jobApi.js | 18 +++++- frontend/src/config/router.config.js | 25 ++++---- frontend/src/views/job/WorkflowList.vue | 53 +++++++++-------- 7 files changed, 119 insertions(+), 59 deletions(-) diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/controller/WorkflowController.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/controller/WorkflowController.java index e8949caa..692b1dee 100644 --- a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/controller/WorkflowController.java +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/controller/WorkflowController.java @@ -37,7 +37,7 @@ public class WorkflowController { @GetMapping("/page/list") @LoginRequired(role = RoleEnum.USER) public PageResult> listPage(WorkflowQueryVO queryVO) { - return workflowService.listPage(queryVO); + return workflowService.listPage(queryVO); } @PutMapping @@ -49,7 +49,17 @@ public class WorkflowController { @GetMapping("{id}") @LoginRequired(role = RoleEnum.USER) public WorkflowDetailResponseVO getWorkflowDetail(@PathVariable("id") Long id) throws IOException { - return workflowService.getWorkflowDetail(id); + return workflowService.getWorkflowDetail(id); + } + + @PutMapping("/update/status/{id}") + public Boolean updateStatus(@PathVariable("id") Long id) { + return workflowService.updateStatus(id); + } + + @DeleteMapping("/{id}") + public Boolean deleteById(@PathVariable("id") Long id) { + return workflowService.deleteById(id); } @PostMapping("/start") diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/response/WorkflowDetailResponseVO.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/response/WorkflowDetailResponseVO.java index 57dfae7c..d1338627 100644 --- a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/response/WorkflowDetailResponseVO.java +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/response/WorkflowDetailResponseVO.java @@ -18,6 +18,11 @@ public class WorkflowDetailResponseVO { */ private Long id; + /** + * 组名称 + */ + private String workflowName; + /** * 组名称 */ diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/WorkflowService.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/WorkflowService.java index 95bbb183..e16aec54 100644 --- a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/WorkflowService.java +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/WorkflowService.java @@ -23,4 +23,8 @@ public interface WorkflowService { PageResult> listPage(WorkflowQueryVO queryVO); Boolean updateWorkflow(WorkflowRequestVO workflowRequestVO); + + Boolean updateStatus(Long id); + + Boolean deleteById(Long id); } diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/impl/WorkflowServiceImpl.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/impl/WorkflowServiceImpl.java index 9ed210cc..287545d1 100644 --- a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/impl/WorkflowServiceImpl.java +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/service/impl/WorkflowServiceImpl.java @@ -76,7 +76,7 @@ public class WorkflowServiceImpl implements WorkflowService { workflow.setNextTriggerAt(calculateNextTriggerAt(workflowRequestVO, DateUtils.toNowMilli())); workflow.setFlowInfo(StrUtil.EMPTY); workflow.setBucketIndex(HashUtil.bkdrHash(workflowRequestVO.getGroupName() + workflowRequestVO.getWorkflowName()) - % systemProperties.getBucketTotal()); + % systemProperties.getBucketTotal()); workflow.setNamespaceId(UserSessionUtils.currentUserSession().getNamespaceId()); Assert.isTrue(1 == workflowMapper.insert(workflow), () -> new EasyRetryServerException("新增工作流失败")); @@ -85,7 +85,7 @@ public class WorkflowServiceImpl implements WorkflowService { // 递归构建图 buildGraph(Lists.newArrayList(SystemConstants.ROOT), new LinkedBlockingDeque<>(), - workflowRequestVO.getGroupName(), workflow.getId(), nodeConfig, graph); + workflowRequestVO.getGroupName(), workflow.getId(), nodeConfig, graph); log.info("图构建完成. graph:[{}]", graph); // 保存图信息 @@ -113,21 +113,21 @@ public class WorkflowServiceImpl implements WorkflowService { WorkflowDetailResponseVO responseVO = WorkflowConverter.INSTANCE.toWorkflowDetailResponseVO(workflow); List workflowNodes = workflowNodeMapper.selectList(new LambdaQueryWrapper() - .eq(WorkflowNode::getDeleted, 0) - .eq(WorkflowNode::getWorkflowId, id) - .orderByAsc(WorkflowNode::getPriorityLevel)); + .eq(WorkflowNode::getDeleted, 0) + .eq(WorkflowNode::getWorkflowId, id) + .orderByAsc(WorkflowNode::getPriorityLevel)); List nodeInfos = WorkflowConverter.INSTANCE.toNodeInfo(workflowNodes); Map workflowNodeMap = nodeInfos.stream() - .collect(Collectors.toMap(WorkflowDetailResponseVO.NodeInfo::getId, i -> i)); + .collect(Collectors.toMap(WorkflowDetailResponseVO.NodeInfo::getId, i -> i)); String flowInfo = workflow.getFlowInfo(); try { MutableGraph graph = GraphUtils.deserializeJsonToGraph(flowInfo); // 反序列化构建图 WorkflowDetailResponseVO.NodeConfig config = buildNodeConfig(graph, SystemConstants.ROOT, new HashMap<>(), - workflowNodeMap); + workflowNodeMap); responseVO.setNodeConfig(config); } catch (Exception e) { log.error("反序列化失败. json:[{}]", flowInfo, e); @@ -159,8 +159,8 @@ public class WorkflowServiceImpl implements WorkflowService { Assert.notNull(workflowRequestVO.getId(), () -> new EasyRetryServerException("工作流ID不能为空")); Assert.isTrue(workflowMapper.selectCount(new LambdaQueryWrapper() - .eq(Workflow::getId, workflowRequestVO.getId())) > 0, - () -> new EasyRetryServerException("工作流不存在")); + .eq(Workflow::getId, workflowRequestVO.getId())) > 0, + () -> new EasyRetryServerException("工作流不存在")); MutableGraph graph = GraphBuilder.directed().allowsSelfLoops(false).build(); // 添加虚拟头节点 @@ -171,7 +171,7 @@ public class WorkflowServiceImpl implements WorkflowService { // 递归构建图 buildGraph(Lists.newArrayList(SystemConstants.ROOT), new LinkedBlockingDeque<>(), - workflowRequestVO.getGroupName(), workflowRequestVO.getId(), nodeConfig, graph); + workflowRequestVO.getGroupName(), workflowRequestVO.getId(), nodeConfig, graph); log.info("图构建完成. graph:[{}]", graph); @@ -184,10 +184,35 @@ public class WorkflowServiceImpl implements WorkflowService { return Boolean.TRUE; } + @Override + public Boolean updateStatus(Long id) { + Workflow workflow = workflowMapper.selectOne( + new LambdaQueryWrapper() + .select(Workflow::getId, Workflow::getWorkflowStatus) + .eq(Workflow::getId, id)); + Assert.notNull(workflow, () -> new EasyRetryServerException("工作流不存在")); + + if (Objects.equals(workflow.getWorkflowStatus(), StatusEnum.NO.getStatus())) { + workflow.setWorkflowStatus(StatusEnum.YES.getStatus()); + } else { + workflow.setWorkflowStatus(StatusEnum.NO.getStatus()); + } + + return 1 == workflowMapper.updateById(workflow); + } + + @Override + public Boolean deleteById(Long id) { + Workflow workflow = new Workflow(); + workflow.setId(id); + workflow.setDeleted(StatusEnum.YES.getStatus()); + return 1 == workflowMapper.updateById(workflow); + } + private WorkflowDetailResponseVO.NodeConfig buildNodeConfig(MutableGraph graph, - Long parentId, - Map nodeConfigMap, - Map workflowNodeMap) { + Long parentId, + Map nodeConfigMap, + Map workflowNodeMap) { Set successors = graph.successors(parentId); if (CollectionUtils.isEmpty(successors)) { @@ -254,7 +279,7 @@ public class WorkflowServiceImpl implements WorkflowService { } public void buildGraph(List parentIds, LinkedBlockingDeque deque, String groupName, Long workflowId, - NodeConfig nodeConfig, MutableGraph graph) { + NodeConfig nodeConfig, MutableGraph graph) { if (Objects.isNull(nodeConfig)) { return; @@ -273,7 +298,7 @@ public class WorkflowServiceImpl implements WorkflowService { } Assert.isTrue(1 == workflowNodeMapper.insert(workflowNode), - () -> new EasyRetryServerException("新增工作流节点失败")); + () -> new EasyRetryServerException("新增工作流节点失败")); // 添加节点 graph.addNode(workflowNode.getId()); for (final Long parentId : parentIds) { @@ -281,11 +306,11 @@ public class WorkflowServiceImpl implements WorkflowService { graph.putEdge(parentId, workflowNode.getId()); } log.warn("workflowNodeId:[{}] parentIds:[{}]", - workflowNode.getId(), JsonUtil.toJsonString(parentIds)); + workflowNode.getId(), JsonUtil.toJsonString(parentIds)); NodeConfig childNode = nodeInfo.getChildNode(); if (Objects.nonNull(childNode) && !CollectionUtils.isEmpty(childNode.getConditionNodes())) { buildGraph(Lists.newArrayList(workflowNode.getId()), deque, groupName, workflowId, childNode, - graph); + graph); } else { // 叶子节点记录一下 deque.add(workflowNode.getId()); diff --git a/frontend/src/api/jobApi.js b/frontend/src/api/jobApi.js index 6904308a..2df13695 100644 --- a/frontend/src/api/jobApi.js +++ b/frontend/src/api/jobApi.js @@ -35,11 +35,27 @@ const jobApi = { updateWorkflow: '/workflow', workflowDetail: '/workflow', workflowBatchListPage: '/workflow/batch/page/list', - workflowBatchDetail: '/workflow/batch/' + workflowBatchDetail: '/workflow/batch/', + updateStatus: '/workflow/update/status/', + delWorkflow: '/workflow/' } export default jobApi +export function delWorkflow (id) { + return request({ + url: jobApi.delWorkflow + id, + method: 'delete' + }) +} + +export function updateWorkflowStatus (id) { + return request({ + url: jobApi.updateStatus + id, + method: 'put' + }) +} + export function workflowBatchDetail (id) { return request({ url: jobApi.workflowBatchDetail + id, diff --git a/frontend/src/config/router.config.js b/frontend/src/config/router.config.js index 1ff1818f..803db8b4 100644 --- a/frontend/src/config/router.config.js +++ b/frontend/src/config/router.config.js @@ -209,19 +209,6 @@ export const asyncRouterMap = [ component: () => import('@/views/job/JobTaskList'), meta: { title: '任务项', icon: 'profile', permission: ['jobBatch'] } }, - { - path: '/job/notify/list', - name: 'JobNotifyList', - component: () => import('@/views/job/JobNotifyList'), - meta: { title: '通知列表', icon: 'profile', keepAlive: true, permission: ['jobNotify'] } - }, - { - path: '/job/notify/config', - name: 'JobNotifyForm', - hidden: true, - component: () => import('@/views/job/form/JobNotifyForm.vue'), - meta: { title: '通知配置', icon: 'profile', keepAlive: true, permission: ['jobNotify'] } - }, { path: '/job/workflow/list', name: 'WorkflowList', @@ -254,6 +241,18 @@ export const asyncRouterMap = [ hidden: true, component: () => import('@/views/job/WorkflowBatchDetail'), meta: { title: '工作流任务批次详情', icon: 'profile', permission: ['jobBatch'] } + }, { + path: '/job/notify/list', + name: 'JobNotifyList', + component: () => import('@/views/job/JobNotifyList'), + meta: { title: '通知列表', icon: 'profile', keepAlive: true, permission: ['jobNotify'] } + }, + { + path: '/job/notify/config', + name: 'JobNotifyForm', + hidden: true, + component: () => import('@/views/job/form/JobNotifyForm.vue'), + meta: { title: '通知配置', icon: 'profile', keepAlive: true, permission: ['jobNotify'] } } ] }, diff --git a/frontend/src/views/job/WorkflowList.vue b/frontend/src/views/job/WorkflowList.vue index 913b33d9..ea26d781 100644 --- a/frontend/src/views/job/WorkflowList.vue +++ b/frontend/src/views/job/WorkflowList.vue @@ -106,28 +106,38 @@ title="是否关闭?" ok-text="关闭" cancel-text="取消" - @confirm="handleClose(record)" + @confirm="handleOpenOrClose(record)" > - 关闭 + 关闭 - + - 开启 + 开启 - + - 删除 + 删除 + + + + 复制 @@ -153,13 +163,13 @@ import ATextarea from 'ant-design-vue/es/input/TextArea' import AInput from 'ant-design-vue/es/input/Input' import { STable, Drawer } from '@/components' -import { delJob, workflowListPage, triggerJob, updateJobStatus } from '@/api/jobApi' +import { workflowListPage, triggerJob, updateWorkflowStatus, delWorkflow } from '@/api/jobApi' import { getAllGroupNameList } from '@/api/manage' import enums from '@/utils/jobEnum' import JobInfo from '@/views/job/JobInfo' export default { - name: 'JobList', + name: 'WorkflowList', components: { AInput, ATextarea, @@ -295,17 +305,6 @@ export default { this.$router.push({ path: '/job/workflow/detail', query: { id: record.id } }) }, handleOk (record) {}, - handleClose (record) { - updateJobStatus({ id: record.id, jobStatus: 0 }).then((res) => { - const { status } = res - if (status === 0) { - this.$message.error('关闭失败') - } else { - this.$refs.table.refresh(true) - this.$message.success('关闭成功') - } - }) - }, handleTrigger (record) { triggerJob(record.id).then((res) => { const { status } = res @@ -317,19 +316,21 @@ export default { } }) }, - handleOpen (record) { - updateJobStatus({ id: record.id, jobStatus: 1 }).then((res) => { + handleOpenOrClose (record) { + updateWorkflowStatus(record.id).then((res) => { const { status } = res if (status === 0) { - this.$message.error('开启失败') + this.$message.error('执行失败') } else { this.$refs.table.refresh(true) - this.$message.success('开启成功') + this.$message.success('执行成功') } }) }, + handleCopy (record) { + }, handleDel (record) { - delJob(record.id).then((res) => { + delWorkflow(record.id).then((res) => { const { status } = res if (status === 0) { this.$message.error('删除失败')