From a7ae8bab24dcbe2e2e4e1d262367b6c7e99792cf Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 11 Feb 2026 17:47:12 +0800 Subject: [PATCH 1/6] add detail --- .../api/controller/FlowRecordController.java | 23 ++++++ .../api/controller/WorkflowController.java | 2 - .../infra/jpa/WorkflowEntityRepository.java | 7 ++ .../com/codingapi/flow/infra/pojo/Select.java | 14 ++++ .../controller/WorkflowQueryController.java | 6 ++ frontend/apps/app-pc/src/pages/todo.tsx | 71 +++++++++++++------ .../packages/flow-design/src/api/record.ts | 6 ++ .../packages/flow-design/src/api/workflow.ts | 4 ++ .../src/components/approval/index.tsx | 46 ++++++++++++ .../src/components/select/index.tsx | 54 ++++++++++++++ frontend/packages/flow-design/src/index.ts | 4 +- 11 files changed, 213 insertions(+), 24 deletions(-) create mode 100644 flow-engine-starter-api/src/main/java/com/codingapi/flow/api/controller/FlowRecordController.java create mode 100644 flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/pojo/Select.java create mode 100644 frontend/packages/flow-design/src/api/record.ts create mode 100644 frontend/packages/flow-design/src/components/approval/index.tsx create mode 100644 frontend/packages/flow-design/src/components/select/index.tsx diff --git a/flow-engine-starter-api/src/main/java/com/codingapi/flow/api/controller/FlowRecordController.java b/flow-engine-starter-api/src/main/java/com/codingapi/flow/api/controller/FlowRecordController.java new file mode 100644 index 00000000..73f705a7 --- /dev/null +++ b/flow-engine-starter-api/src/main/java/com/codingapi/flow/api/controller/FlowRecordController.java @@ -0,0 +1,23 @@ +package com.codingapi.flow.api.controller; + +import com.codingapi.springboot.framework.dto.request.IdRequest; +import com.codingapi.springboot.framework.dto.response.Response; +import com.codingapi.springboot.framework.dto.response.SingleResponse; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/cmd/record") +@AllArgsConstructor +public class FlowRecordController { + + @GetMapping("/detail") + public Response detail(IdRequest request) { + String id = request.getStringId(); + System.out.println("id:" + id); + return SingleResponse.empty(); + } + +} diff --git a/flow-engine-starter-api/src/main/java/com/codingapi/flow/api/controller/WorkflowController.java b/flow-engine-starter-api/src/main/java/com/codingapi/flow/api/controller/WorkflowController.java index 6bccbeb6..10a3acdf 100644 --- a/flow-engine-starter-api/src/main/java/com/codingapi/flow/api/controller/WorkflowController.java +++ b/flow-engine-starter-api/src/main/java/com/codingapi/flow/api/controller/WorkflowController.java @@ -14,7 +14,6 @@ import com.codingapi.springboot.framework.dto.response.Response; import com.codingapi.springboot.framework.dto.response.SingleResponse; import com.codingapi.springboot.framework.user.UserContext; -import jakarta.transaction.Transactional; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -24,7 +23,6 @@ @RestController @RequestMapping("/api/cmd/workflow") @AllArgsConstructor -@Transactional public class WorkflowController { private final WorkflowRepository workflowRepository; diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/WorkflowEntityRepository.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/WorkflowEntityRepository.java index 4182f130..824b5f8d 100644 --- a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/WorkflowEntityRepository.java +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/WorkflowEntityRepository.java @@ -1,9 +1,16 @@ package com.codingapi.flow.infra.jpa; import com.codingapi.flow.infra.entity.WorkflowEntity; +import com.codingapi.flow.infra.pojo.Select; import com.codingapi.springboot.fast.jpa.repository.FastRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; public interface WorkflowEntityRepository extends FastRepository { WorkflowEntity getWorkflowEntityById(String id); + + @Query("select new com.codingapi.flow.infra.pojo.Select(w.title,w.code) from WorkflowEntity w where w.enable = true") + List options() { + return MultiResponse.of(workflowEntityRepository.options()); + } + } diff --git a/frontend/apps/app-pc/src/pages/todo.tsx b/frontend/apps/app-pc/src/pages/todo.tsx index 393b028a..574fdedf 100644 --- a/frontend/apps/app-pc/src/pages/todo.tsx +++ b/frontend/apps/app-pc/src/pages/todo.tsx @@ -1,14 +1,24 @@ import React from "react"; -import {list,todo,done} from "@/api/record.ts"; -import {type ActionType, type TableProps,Table} from "@flow-engine/flow-design"; -import {Button, Space, Tabs,type TabsProps } from "antd"; +import {done, list, todo} from "@/api/record.ts"; +import { + type ActionType, + ApprovalPanelDrawer, + Table, + type TableProps, + WorkflowSelectModal +} from "@flow-engine/flow-design"; +import {Button, Space, Tabs, type TabsProps} from "antd"; -const TodoPage:React.FC = ()=>{ +const TodoPage: React.FC = () => { const actionAll = React.useRef(null); const actionTodo = React.useRef(null); const actionDone = React.useRef(null); + const [selectVisible, setSelectVisible] = React.useState(false); + const [approvalVisible, setApprovalVisible] = React.useState(false); + const [workflowCode, setWorkflowCode] = React.useState(''); + const columns: TableProps['columns'] = [ { dataIndex: 'id', @@ -49,12 +59,11 @@ const TodoPage:React.FC = ()=>{ } ]; - - const items:TabsProps['items'] = [ + const items: TabsProps['items'] = [ { - key:'all', - label:'全部流程', - children:( + key: 'all', + label: '全部流程', + children: ( { ) }, { - key:'todo', - label:'我的待办', - children:( + key: 'todo', + label: '我的待办', + children: (
{ ) }, { - key:'done', - label:'我的已办', - children:( + key: 'done', + label: '我的已办', + children: (
{ { - if(currentKey==='all'){ + onChange={(currentKey) => { + if (currentKey === 'all') { actionAll.current?.reload(); } - if(currentKey==='done'){ + if (currentKey === 'done') { actionDone.current?.reload(); } - if(currentKey==='todo'){ + if (currentKey === 'todo') { actionTodo.current?.reload(); } }} tabBarExtraContent={{ - right:( + right: ( ) }} /> + + { + setWorkflowCode(code); + setSelectVisible(false); + setApprovalVisible(true); + }} + onClose={() => { + setSelectVisible(false); + }} + /> + + { + setApprovalVisible(false); + }} + /> ) } diff --git a/frontend/packages/flow-design/src/api/record.ts b/frontend/packages/flow-design/src/api/record.ts new file mode 100644 index 00000000..044b79c9 --- /dev/null +++ b/frontend/packages/flow-design/src/api/record.ts @@ -0,0 +1,6 @@ +import { httpClient } from "."; + +export const detail = (id:string) => { + return httpClient.get('/api/cmd/record/detail',{id}); +} + diff --git a/frontend/packages/flow-design/src/api/workflow.ts b/frontend/packages/flow-design/src/api/workflow.ts index 39b1204a..f9d4567b 100644 --- a/frontend/packages/flow-design/src/api/workflow.ts +++ b/frontend/packages/flow-design/src/api/workflow.ts @@ -4,6 +4,10 @@ export const list = (request: any) => { return httpClient.page('/api/query/workflow/list', request, {}, {}, []); } +export const options = () => { + return httpClient.get('/api/query/workflow/options'); +} + export const remove = (id:string) => { return httpClient.post('/api/cmd/workflow/remove',{id}); } diff --git a/frontend/packages/flow-design/src/components/approval/index.tsx b/frontend/packages/flow-design/src/components/approval/index.tsx new file mode 100644 index 00000000..c17e5306 --- /dev/null +++ b/frontend/packages/flow-design/src/components/approval/index.tsx @@ -0,0 +1,46 @@ +import React from "react"; +import {Drawer} from "@/components/drawer"; +import {detail} from "@/api/record"; + + +interface ApprovalPanelProps { + workflowCode?: string; + recordId?:string +} + +export const ApprovalPanel: React.FC = (props) => { + + React.useEffect(()=>{ + const id = props.workflowCode || props.recordId || ''; + detail(id).then(res=>{ + if(res.success){ + console.log(res.data) + } + }); + },[]); + + return ( + <>approval + ) +} + +interface ApprovalPanelDrawerProps extends ApprovalPanelProps { + open: boolean; + onClose: () => void; +} + +export const ApprovalPanelDrawer: React.FC = (props) => { + + return ( + + + + ) +} \ No newline at end of file diff --git a/frontend/packages/flow-design/src/components/select/index.tsx b/frontend/packages/flow-design/src/components/select/index.tsx new file mode 100644 index 00000000..f1597e67 --- /dev/null +++ b/frontend/packages/flow-design/src/components/select/index.tsx @@ -0,0 +1,54 @@ +import React from "react"; +import {options} from "@/api/workflow"; +import {Button, Modal, Space} from "antd"; + +interface Select { + label: string; + value: string; +} + +interface WorkflowSelectModalProps { + open: boolean; + onClose: () => void; + onSelect?:(code: string) => void; +} + +export const WorkflowSelectModal: React.FC = (props) => { + + const [option, setOption] = React.useState([]); + + React.useEffect(() => { + options().then(res => { + if (res.success) { + setOption(res.data.list); + } + }) + }, []); + + return ( + + + {option.map((item, index) => { + return ( + + ) + })} + + + ) +} \ No newline at end of file diff --git a/frontend/packages/flow-design/src/index.ts b/frontend/packages/flow-design/src/index.ts index 9b7de096..d00ed073 100644 --- a/frontend/packages/flow-design/src/index.ts +++ b/frontend/packages/flow-design/src/index.ts @@ -1,3 +1,5 @@ export * from '@/pages/design-list'; export * from '@/pages/design-panel'; -export * from '@/components/table'; \ No newline at end of file +export * from '@/components/table'; +export * from '@/components/select'; +export * from '@/components/approval'; \ No newline at end of file From a74c6996ab4a639fdc0cbec6228ef89fee807c99 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 11 Feb 2026 18:32:38 +0800 Subject: [PATCH 2/6] add detail --- .../flow/pojo/body/FlowAdviceBody.java | 3 + .../flow/pojo/response/FlowContent.java | 157 ++++++++++++++++++ .../codingapi/flow/service/FlowService.java | 18 +- .../flow/service/impl/FlowDetailService.java | 74 +++++++++ .../api/controller/FlowRecordController.java | 9 +- .../infra/jpa/WorkflowEntityRepository.java | 2 +- .../com/codingapi/flow/AutoConfiguration.java | 22 +++ 7 files changed, 278 insertions(+), 7 deletions(-) create mode 100644 flow-engine-framework/src/main/java/com/codingapi/flow/pojo/response/FlowContent.java create mode 100644 flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowDetailService.java diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/pojo/body/FlowAdviceBody.java b/flow-engine-framework/src/main/java/com/codingapi/flow/pojo/body/FlowAdviceBody.java index ca0a7960..3ca1a771 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/pojo/body/FlowAdviceBody.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/pojo/body/FlowAdviceBody.java @@ -8,6 +8,9 @@ import java.util.List; +/** + * 流程审批意见 + */ @Data @NoArgsConstructor public class FlowAdviceBody { diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/pojo/response/FlowContent.java b/flow-engine-framework/src/main/java/com/codingapi/flow/pojo/response/FlowContent.java new file mode 100644 index 00000000..6a897873 --- /dev/null +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/pojo/response/FlowContent.java @@ -0,0 +1,157 @@ +package com.codingapi.flow.pojo.response; + +import com.codingapi.flow.action.IFlowAction; +import com.codingapi.flow.form.FormMeta; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +/** + * 流程详情 + */ +@Data +public class FlowContent { + + /** + * 流程记录编号 + */ + private long recordId; + /** + * 流程编号 + */ + private String workflowCode; + /** + * 流程视图 + */ + private String view; + + /** + * 表单元数据 + */ + private FormMeta form; + /** + * 流程记录 + */ + private List todos; + + /** + * 流程按钮 + */ + private List actions; + + /** + * 是否可合并 + */ + private boolean mergeable; + + /** + * 发起者id + */ + private long createOperatorId; + + /** + * 历史记录 + */ + private List histories; + + /** + * 下一审批 + */ + private List nextNodes; + + /** + * 流程图 + */ + @Data + public static class NextNode{ + /** + * 节点名称 + */ + private String nodeId; + /** + * 节点名称 + */ + private String nodeName; + /** + * 节点类型 + */ + private String nodeType; + } + + @Data + public static class History{ + /** + * 流程编号 + */ + private long recordId; + /** + * 流程标题 + */ + private String title; + + /** + * 审批意见 + */ + private String advice; + + /** + * 签名key + */ + private String signKey; + + /** + * 节点名称 + */ + private String nodeName; + + /** + * 节点id + */ + private String nodeId; + /** + * 节点类型 + */ + private String nodeType; + + /** + * 更新时间 + */ + private long updateTime; + + /** + * 当前审批人Id + */ + private long currentOperatorId; + + /** + * 当前审批人名称 + */ + private String currentOperatorName; + } + + @Data + public static class Body { + /** + * 流程记录编号 + */ + private long recordId; + /** + * 流程标题 + */ + private String title; + /** + * 表单数据 + */ + private Map data; + + /** + * 节点状态 | 待办、已办 + */ + private int recordState; + /** + * 流程状态 | 运行中、已完成、异常、删除 + */ + private int flowState; + } +} diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/service/FlowService.java b/flow-engine-framework/src/main/java/com/codingapi/flow/service/FlowService.java index a9890c53..fc83b1be 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/service/FlowService.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/service/FlowService.java @@ -2,15 +2,14 @@ import com.codingapi.flow.context.RepositoryHolderContext; import com.codingapi.flow.gateway.FlowOperatorGateway; +import com.codingapi.flow.operator.IFlowOperator; import com.codingapi.flow.pojo.request.FlowActionRequest; import com.codingapi.flow.pojo.request.FlowCreateRequest; import com.codingapi.flow.pojo.request.FlowRevokeRequest; import com.codingapi.flow.pojo.request.FlowUrgeRequest; +import com.codingapi.flow.pojo.response.FlowContent; import com.codingapi.flow.repository.*; -import com.codingapi.flow.service.impl.FlowActionService; -import com.codingapi.flow.service.impl.FlowCreateService; -import com.codingapi.flow.service.impl.FlowRevokeService; -import com.codingapi.flow.service.impl.FlowUrgeService; +import com.codingapi.flow.service.impl.*; /** * 流程服务 @@ -46,6 +45,17 @@ public FlowService(WorkflowRepository workflowRepository, urgeIntervalRepository); } + /** + * 流程详情 + * @param id 流程id 或者workflowCode + * @param currentOperator 当前操作人 + * @return 流程详情 + */ + public FlowContent detail(String id,IFlowOperator currentOperator) { + FlowDetailService flowDetailService = new FlowDetailService(id,currentOperator,flowRecordRepository, flowOperatorGateway,workflowRepository, workflowBackupRepository); + return flowDetailService.detail(); + } + /** * 创建流程 * diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowDetailService.java b/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowDetailService.java new file mode 100644 index 00000000..d84aee03 --- /dev/null +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowDetailService.java @@ -0,0 +1,74 @@ +package com.codingapi.flow.service.impl; + +import com.codingapi.flow.backup.WorkflowBackup; +import com.codingapi.flow.exception.FlowNotFoundException; +import com.codingapi.flow.gateway.FlowOperatorGateway; +import com.codingapi.flow.operator.IFlowOperator; +import com.codingapi.flow.pojo.response.FlowContent; +import com.codingapi.flow.record.FlowRecord; +import com.codingapi.flow.repository.FlowRecordRepository; +import com.codingapi.flow.repository.WorkflowBackupRepository; +import com.codingapi.flow.repository.WorkflowRepository; +import com.codingapi.flow.workflow.Workflow; +import lombok.AllArgsConstructor; + +public class FlowDetailService { + + private final String id; + private final IFlowOperator currentOperator; + private final FlowRecordRepository flowRecordRepository; + private final FlowOperatorGateway flowOperatorGateway; + private final WorkflowRepository workflowRepository; + private final WorkflowBackupRepository workflowBackupRepository; + + public FlowDetailService(String id, + IFlowOperator currentOperator, + FlowRecordRepository flowRecordRepository, + FlowOperatorGateway flowOperatorGateway, + WorkflowRepository workflowRepository, + WorkflowBackupRepository workflowBackupRepository) { + this.id = id; + this.currentOperator = currentOperator; + this.flowRecordRepository = flowRecordRepository; + this.flowOperatorGateway = flowOperatorGateway; + this.workflowRepository = workflowRepository; + this.workflowBackupRepository = workflowBackupRepository; + } + + + private boolean isCreateWorkflow() { + return !id.matches("^[0-9]+$"); + } + + public FlowContent detail() { + if (this.isCreateWorkflow()) { + Workflow workflow = workflowRepository.get(id); + if (workflow == null) { + throw FlowNotFoundException.workflow(id); + } + return new FlowContentFactory(workflow, null).create(); + } else { + FlowRecord flowRecord = flowRecordRepository.get(Long.parseLong(id)); + if (flowRecord == null) { + throw FlowNotFoundException.record(Long.parseLong(id)); + } + WorkflowBackup workflowBackup = workflowBackupRepository.get(flowRecord.getWorkBackupId()); + if (workflowBackup == null) { + throw FlowNotFoundException.workflow(flowRecord.getWorkBackupId() + " not found"); + } + Workflow workflow = workflowBackup.toWorkflow(); + return new FlowContentFactory(workflow, flowRecord).create(); + } + } + + + @AllArgsConstructor + private static class FlowContentFactory { + private final Workflow workflow; + private final FlowRecord flowRecord; + + public FlowContent create() { + return new FlowContent(); + } + } +} diff --git a/flow-engine-starter-api/src/main/java/com/codingapi/flow/api/controller/FlowRecordController.java b/flow-engine-starter-api/src/main/java/com/codingapi/flow/api/controller/FlowRecordController.java index 73f705a7..68cc0960 100644 --- a/flow-engine-starter-api/src/main/java/com/codingapi/flow/api/controller/FlowRecordController.java +++ b/flow-engine-starter-api/src/main/java/com/codingapi/flow/api/controller/FlowRecordController.java @@ -1,8 +1,11 @@ package com.codingapi.flow.api.controller; +import com.codingapi.flow.operator.IFlowOperator; +import com.codingapi.flow.service.FlowService; import com.codingapi.springboot.framework.dto.request.IdRequest; import com.codingapi.springboot.framework.dto.response.Response; import com.codingapi.springboot.framework.dto.response.SingleResponse; +import com.codingapi.springboot.framework.user.UserContext; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -13,11 +16,13 @@ @AllArgsConstructor public class FlowRecordController { + private final FlowService flowService; + @GetMapping("/detail") public Response detail(IdRequest request) { String id = request.getStringId(); - System.out.println("id:" + id); - return SingleResponse.empty(); + IFlowOperator current = (IFlowOperator) UserContext.getInstance().current(); + return SingleResponse.of(flowService.detail(id, current)); } } diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/WorkflowEntityRepository.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/WorkflowEntityRepository.java index 824b5f8d..a8ffa1a2 100644 --- a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/WorkflowEntityRepository.java +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/WorkflowEntityRepository.java @@ -11,6 +11,6 @@ public interface WorkflowEntityRepository extends FastRepository options(); } diff --git a/flow-engine-starter/src/main/java/com/codingapi/flow/AutoConfiguration.java b/flow-engine-starter/src/main/java/com/codingapi/flow/AutoConfiguration.java index c4b1bacb..cdd4ba7e 100644 --- a/flow-engine-starter/src/main/java/com/codingapi/flow/AutoConfiguration.java +++ b/flow-engine-starter/src/main/java/com/codingapi/flow/AutoConfiguration.java @@ -6,6 +6,7 @@ import com.codingapi.flow.register.GatewayContextRegister; import com.codingapi.flow.repository.*; import com.codingapi.flow.runner.FlowDelayTaskRunner; +import com.codingapi.flow.service.FlowService; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -52,4 +53,25 @@ public RepositoryHolderContextRegister repositoryHolderContextRegister( urgeIntervalRepository ); } + + @Bean + public FlowService flowService( + WorkflowRepository workflowRepository, + FlowOperatorGateway flowOperatorGateway, + FlowRecordRepository flowRecordRepository, + WorkflowBackupRepository workflowBackupRepository, + ParallelBranchRepository parallelBranchRepository, + DelayTaskRepository delayTaskRepository, + UrgeIntervalRepository urgeIntervalRepository + ) { + return new FlowService( + workflowRepository, + flowOperatorGateway, + flowRecordRepository, + workflowBackupRepository, + parallelBranchRepository, + delayTaskRepository, + urgeIntervalRepository + ); + } } From 3074f66e88246607a16eb953063f8712b6ee87f3 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 11 Feb 2026 20:51:47 +0800 Subject: [PATCH 3/6] #30 --- .../com/codingapi/flow/record/FlowRecord.java | 41 ++++- .../flow/repository/FlowRecordRepository.java | 17 ++ .../strategy/node/RecordMergeStrategy.java | 2 + .../repository/FlowRecordRepositoryImpl.java | 10 +- .../service/FlowMergeableServiceTest.java | 150 ++++++++++++++++++ .../infra/convert/FlowRecordConvertor.java | 8 + .../flow/infra/entity/FlowRecordEntity.java | 21 +++ .../infra/jpa/FlowRecordEntityRepository.java | 22 ++- .../impl/FlowRecordRepositoryImpl.java | 8 +- .../controller/FlowRecordQueryController.java | 4 +- 10 files changed, 258 insertions(+), 25 deletions(-) create mode 100644 flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowRecord.java b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowRecord.java index a637f16e..272b0107 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowRecord.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowRecord.java @@ -99,15 +99,25 @@ public class FlowRecord { private String signKey; /** - * 当前审批人 + * 当前审批人Id */ private long currentOperatorId; /** - * 代替的审批人 + * 当前审批人名称 + */ + private String currentOperatorName; + + /** + * 代替的审批人Id */ private long forwardOperatorId; + /** + * 代替的审批人名称 + */ + private String forwardOperatorName; + /** * 有那个节点退回的 */ @@ -164,6 +174,11 @@ public class FlowRecord { * 发起者id */ private long createOperatorId; + /** + * 发起者名称 + */ + private String createOperatorName; + /** * 异常信息 */ @@ -175,13 +190,19 @@ public class FlowRecord { private long timeoutTime; /** * 是否可合并 + * 合并的数据,相同的 {@link FlowRecord#currentOperatorId} {@link FlowRecord#workBackupId} {@link FlowRecord#nodeId}字段的数据合并到一条记录上,待办列表中只展示最新的一条记录和总数。 */ private boolean mergeable; /** - * 被干预的用户 + * 被干预的用户Id */ private long interferedOperatorId; + /** + * 被干预的用户名称 + */ + private String interferedOperatorName; + /** * 委托记录id */ @@ -217,11 +238,21 @@ public FlowRecord(FlowSession flowSession, int nodeOrder) { this.nodeOrder = nodeOrder; this.processId = RandomUtils.generateStringId(); this.createOperatorId = flowSession.getCreatedOperator().getUserId(); - this.forwardOperatorId = currentOperator.equals(sourceOperator) ? 0 : sourceOperator.getUserId(); + this.createOperatorName = flowSession.getCreatedOperator().getName(); + // 是否转交之后的人来审批的判断 + if(currentOperator.equals(sourceOperator)){ + this.forwardOperatorId = 0; + }else { + this.forwardOperatorId = sourceOperator.getUserId(); + this.forwardOperatorName = sourceOperator.getName(); + } this.recordState = SATE_RECORD_TODO; this.actionId = action.id(); this.actionType = action.type(); + this.currentOperatorId = currentOperator.getUserId(); + this.currentOperatorName = currentOperator.getName(); + this.advice = flowSession.getAdvice().getAdvice(); this.signKey = flowSession.getAdvice().getSignKey(); this.flowState = SATE_FLOW_RUNNING; @@ -347,6 +378,7 @@ public void update(FlowSession flowSession, boolean done) { // 设置流程干预人信息,流程干预只能由流程管理员才能操作 if (flowSession.getCurrentOperator().getUserId() != this.currentOperatorId) { this.interferedOperatorId = flowSession.getCurrentOperator().getUserId(); + this.interferedOperatorName = flowSession.getCurrentOperator().getName(); } if (flowAdvice != null) { @@ -445,6 +477,7 @@ public void resetAddAudit(long fromId, int nodeOrder, long currentOperatorId, bo public FlowRecord create(FlowSession flowSession) { FlowRecord flowRecord = new FlowRecord(flowSession, 0); flowRecord.currentOperatorId = flowSession.getCurrentOperator().getUserId(); + flowRecord.currentOperatorName = flowSession.getCurrentOperator().getName(); return flowRecord; } diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowRecordRepository.java b/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowRecordRepository.java index 6721143d..473be5ff 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowRecordRepository.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowRecordRepository.java @@ -9,12 +9,29 @@ */ public interface FlowRecordRepository { + /** + * 获取流程详细 + * @param id 流程id + * @return 流程记录 + */ FlowRecord get(long id); + /** + * 保存流程 + * @param flowRecord 流程记录 + */ void save(FlowRecord flowRecord); + /** + * 批量保存流程 + * @param flowRecords 流程记录 + */ void saveAll(List flowRecords); + /** + * 删除流程记录 + * @param flowRecord 流程记录 + */ void delete(FlowRecord flowRecord); /** diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/strategy/node/RecordMergeStrategy.java b/flow-engine-framework/src/main/java/com/codingapi/flow/strategy/node/RecordMergeStrategy.java index 47345e4d..6d44384e 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/strategy/node/RecordMergeStrategy.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/strategy/node/RecordMergeStrategy.java @@ -1,6 +1,7 @@ package com.codingapi.flow.strategy.node; import com.codingapi.flow.common.IMapConvertor; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -13,6 +14,7 @@ @Setter @Getter @NoArgsConstructor +@AllArgsConstructor public class RecordMergeStrategy extends BaseStrategy { private boolean enable; diff --git a/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowRecordRepositoryImpl.java b/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowRecordRepositoryImpl.java index 32002769..c0371c60 100644 --- a/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowRecordRepositoryImpl.java +++ b/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowRecordRepositoryImpl.java @@ -60,7 +60,9 @@ public List findCurrentNodeRecords(long fromId, String nodeId) { @Override public List findProcessRecords(String processId) { - return cache.values().stream().filter(flowRecord -> flowRecord.getProcessId().equals(processId)).toList(); + return cache.values().stream().filter(flowRecord -> + flowRecord.getProcessId().equals(processId)) + .toList(); } @Override @@ -68,7 +70,6 @@ public List findTodoRecords(String processId) { return cache.values().stream().filter(flowRecord -> flowRecord.getProcessId().equals(processId) && flowRecord.isTodo() - && !flowRecord.isRevoked() ) .toList(); } @@ -76,7 +77,10 @@ public List findTodoRecords(String processId) { @Override public List findAfterRecords(String processId, long fromId) { return cache.values().stream().filter(flowRecord -> - flowRecord.getProcessId().equals(processId) && flowRecord.getFromId() >= fromId + flowRecord.getProcessId().equals(processId) + && flowRecord.getFromId() >= fromId + && !flowRecord.isRevoked() + && !flowRecord.isHidden() ).toList(); } } diff --git a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java new file mode 100644 index 00000000..84ebbd20 --- /dev/null +++ b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java @@ -0,0 +1,150 @@ +package com.codingapi.flow.service; + +import com.codingapi.flow.action.IFlowAction; +import com.codingapi.flow.action.actions.CustomAction; +import com.codingapi.flow.builder.ActionBuilder; +import com.codingapi.flow.builder.FormFieldPermissionsBuilder; +import com.codingapi.flow.builder.NodeStrategyBuilder; +import com.codingapi.flow.context.GatewayContext; +import com.codingapi.flow.form.FormMeta; +import com.codingapi.flow.form.FormMetaBuilder; +import com.codingapi.flow.form.permission.PermissionType; +import com.codingapi.flow.gateway.impl.UserGateway; +import com.codingapi.flow.node.nodes.ApprovalNode; +import com.codingapi.flow.node.nodes.EndNode; +import com.codingapi.flow.node.nodes.StartNode; +import com.codingapi.flow.pojo.body.FlowAdviceBody; +import com.codingapi.flow.pojo.request.FlowActionRequest; +import com.codingapi.flow.pojo.request.FlowCreateRequest; +import com.codingapi.flow.record.FlowRecord; +import com.codingapi.flow.repository.*; +import com.codingapi.flow.strategy.node.FormFieldPermissionStrategy; +import com.codingapi.flow.strategy.node.OperatorLoadStrategy; +import com.codingapi.flow.strategy.node.RecordMergeStrategy; +import com.codingapi.flow.user.User; +import com.codingapi.flow.workflow.Workflow; +import com.codingapi.flow.workflow.WorkflowBuilder; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class FlowMergeableServiceTest { + + private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); + private final UserGateway userGateway = new UserGateway(); + private final WorkflowBackupRepository workflowBackupRepository = new WorkflowBackupRepositoryImpl(); + private final WorkflowRepository workflowRepository = new WorkflowRepositoryImpl(); + private final ParallelBranchRepository parallelBranchRepository = new ParallelBranchRepositoryImpl(); + private final DelayTaskRepository delayTaskRepository = new DelayTaskRepositoryImpl(); + private final UrgeIntervalRepository urgeIntervalRepository = new UrgeIntervalRepositoryImpl(); + private final FlowService flowService = new FlowService(workflowRepository, userGateway, flowRecordRepository, workflowBackupRepository, parallelBranchRepository, delayTaskRepository, urgeIntervalRepository); + + + /** + * 合并记录测试 + */ + @Test + void mergeableRecords() { + + User user = new User(1, "user"); + User boss = new User(2, "boss"); + userGateway.save(user); + userGateway.save(boss); + + GatewayContext.getInstance().setFlowOperatorGateway(userGateway); + + FormMeta form = FormMetaBuilder.builder() + .name("请假流程") + .code("leave") + .addField("请假人", "name", "string") + .addField("请假天数", "days", "int") + .addField("请假事由", "reason", "string") + .build(); + + StartNode startNode = StartNode + .builder() + .strategies(NodeStrategyBuilder.builder() + .addStrategy(new FormFieldPermissionStrategy(FormFieldPermissionsBuilder.builder() + .addPermission("leave", "name", PermissionType.WRITE) + .addPermission("leave", "days", PermissionType.WRITE) + .addPermission("leave", "reason", PermissionType.WRITE) + .build())) + .build()) + .actions(ActionBuilder.builder() + .addAction(new CustomAction()) + .build()) + .build(); + + ApprovalNode bossNode = ApprovalNode.builder() + .name("经理审批") + .strategies(NodeStrategyBuilder.builder() + .addStrategy(new FormFieldPermissionStrategy(FormFieldPermissionsBuilder.builder() + .addPermission("leave", "name", PermissionType.WRITE) + .addPermission("leave", "days", PermissionType.WRITE) + .addPermission("leave", "reason", PermissionType.WRITE) + .build())) + .addStrategy(new OperatorLoadStrategy("def run(request){return [$bind.getOperatorById(2)]}")) + .addStrategy(new RecordMergeStrategy(true)) + .build() + ) + .build(); + + EndNode endNode = EndNode.builder().build(); + Workflow workflow = WorkflowBuilder.builder() + .title("请假流程") + .code("leave") + .createdOperator(user) + .form(form) + .addNode(startNode) + .addNode(bossNode) + .addNode(endNode) + .build(); + + workflowRepository.save(workflow); + + Map data = Map.of("name", "lorne", "days", 1, "reason", "leave"); + + + int count = 5; + for (int i = 0; i < count; i++) { + List startActions = startNode.actionManager().getActions(); + FlowCreateRequest userCreateRequest = new FlowCreateRequest(); + userCreateRequest.setWorkId(workflow.getId()); + userCreateRequest.setFormData(data); + userCreateRequest.setActionId(startActions.get(0).id()); + userCreateRequest.setOperatorId(user.getUserId()); + flowService.create(userCreateRequest); + + List userRecordList = flowRecordRepository.findTodoByOperator(user.getUserId()); + assertEquals(1, userRecordList.size()); + + FlowActionRequest userRequest = new FlowActionRequest(); + userRequest.setFormData(data); + userRequest.setRecordId(userRecordList.get(0).getId()); + userRequest.setAdvice(new FlowAdviceBody(startActions.get(0).id(), "同意", user.getUserId())); + flowService.action(userRequest); + } + + + List bossRecordList = flowRecordRepository.findTodoByOperator(boss.getUserId()); + assertEquals(count, bossRecordList.size()); + assertEquals(count, bossRecordList.stream().filter(FlowRecord::isMergeable).toList().size()); + + + List bossActions = bossNode.actionManager().getActions(); + + FlowActionRequest bossRequest = new FlowActionRequest(); + bossRequest.setFormData(data); + bossRequest.setRecordId(bossRecordList.get(0).getId()); + bossRequest.setAdvice(new FlowAdviceBody(bossActions.get(0).id(), "同意", boss.getUserId())); + flowService.action(bossRequest); + + List records = flowRecordRepository.findProcessRecords(bossRecordList.get(0).getProcessId()); + assertEquals(3, records.size()); + assertEquals(3, records.stream().filter(FlowRecord::isFinish).toList().size()); + + } +} diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/convert/FlowRecordConvertor.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/convert/FlowRecordConvertor.java index de9fd295..dd4f31e1 100644 --- a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/convert/FlowRecordConvertor.java +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/convert/FlowRecordConvertor.java @@ -27,7 +27,9 @@ public static FlowRecord convert(FlowRecordEntity entity) { entity.getAdvice(), entity.getSignKey(), entity.getCurrentOperatorId(), + entity.getCurrentOperatorName(), entity.getForwardOperatorId(), + entity.getForwardOperatorName(), entity.getReturnNodeId(), entity.getNodeOrder(), entity.getHidden(), @@ -40,10 +42,12 @@ public static FlowRecord convert(FlowRecordEntity entity) { entity.getFinishTime(), entity.getReadable(), entity.getCreateOperatorId(), + entity.getCreateOperatorName(), entity.getErrMessage(), entity.getTimeoutTime(), entity.getMergeable(), entity.getInterferedOperatorId(), + entity.getInterferedOperatorName(), entity.getDelegateId(), entity.getParallelId(), entity.getParallelBranchNodeId(), @@ -70,7 +74,9 @@ public static FlowRecordEntity convert(FlowRecord record) { entity.setAdvice(record.getAdvice()); entity.setSignKey(record.getSignKey()); entity.setCurrentOperatorId(record.getCurrentOperatorId()); + entity.setCurrentOperatorName(record.getCurrentOperatorName()); entity.setForwardOperatorId(record.getForwardOperatorId()); + entity.setForwardOperatorName(record.getForwardOperatorName()); entity.setReturnNodeId(record.getReturnNodeId()); entity.setNodeOrder(record.getNodeOrder()); entity.setHidden(record.isHidden()); @@ -83,10 +89,12 @@ public static FlowRecordEntity convert(FlowRecord record) { entity.setFinishTime(record.getFinishTime()); entity.setReadable(record.isReadable()); entity.setCreateOperatorId(record.getCreateOperatorId()); + entity.setCreateOperatorName(record.getCreateOperatorName()); entity.setErrMessage(record.getErrMessage()); entity.setTimeoutTime(record.getTimeoutTime()); entity.setMergeable(record.isMergeable()); entity.setInterferedOperatorId(record.getInterferedOperatorId()); + entity.setInterferedOperatorName(record.getInterferedOperatorName()); entity.setDelegateId(record.getDelegateId()); entity.setParallelId(record.getParallelId()); entity.setParallelBranchNodeId(record.getParallelBranchNodeId()); diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/entity/FlowRecordEntity.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/entity/FlowRecordEntity.java index e904e98c..5cc38d5a 100644 --- a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/entity/FlowRecordEntity.java +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/entity/FlowRecordEntity.java @@ -77,11 +77,21 @@ public class FlowRecordEntity { */ private Long currentOperatorId; + /** + * 当前审批人名称 + */ + private String currentOperatorName; + /** * 代替的审批人 */ private Long forwardOperatorId; + /** + * 代替的审批人名称 + */ + private String forwardOperatorName; + /** * 有那个节点退回的 */ @@ -136,6 +146,12 @@ public class FlowRecordEntity { * 发起者id */ private Long createOperatorId; + + /** + * 发起者名称 + */ + private String createOperatorName; + /** * 异常信息 */ @@ -154,6 +170,11 @@ public class FlowRecordEntity { */ private Long interferedOperatorId; + /** + * 被干预的用户名称 + */ + private String interferedOperatorName; + /** * 委托记录id */ diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowRecordEntityRepository.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowRecordEntityRepository.java index f008bd7e..83bd902e 100644 --- a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowRecordEntityRepository.java +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowRecordEntityRepository.java @@ -12,25 +12,23 @@ public interface FlowRecordEntityRepository extends FastRepository findFlowRecordEntityByProcessId(String processId); + @Query("from FlowRecordEntity r where r.processId = ?1") + List findProcessIdRecords(String processId); - List findFlowRecordEntityByFromIdAndNodeIdAndRevoked(long fromId, String nodeId, boolean revoked); + @Query("from FlowRecordEntity r where r.fromId = ?1 and r.nodeId =?2 and r.revoked = false") + List findCurrentNodeRecords(long fromId, String nodeId); - List findFlowRecordEntityByProcessIdAndRecordStateAndFlowStateAndHiddenAndRevoked(String processId, - int recordState, - int flowState, - boolean hidden, - boolean revoked); - - List findFlowRecordEntityByProcessIdAndFromIdGreaterThanEqual(String processId, long fromId); + @Query("from FlowRecordEntity r where r.processId = ?1 and (r.recordState = 0 and r.flowState = 0 and r.hidden=false and r.revoked = false)") + List findTodoRecords(String processId); + @Query("from FlowRecordEntity r where r.processId = ?1 and r.fromId >=?2 and r.hidden=false and r.revoked = false") + List findAfterRecords(String processId, long fromId); @Query("from FlowRecordEntity r where r.currentOperatorId = ?1 and (r.recordState = 0 and r.flowState = 0 and r.hidden=false and r.revoked = false)") - Page findTodoPage(long operatorId, PageRequest pageRequest); - + Page findTodoRecordPage(long operatorId, PageRequest pageRequest); @Query("from FlowRecordEntity r where r.currentOperatorId = ?1 and (r.recordState = 1 and r.hidden=false and r.revoked = false) ") - Page findDonePage(long operatorId, PageRequest pageRequest); + Page findDoneRecordPage(long operatorId, PageRequest pageRequest); } diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/repository/impl/FlowRecordRepositoryImpl.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/repository/impl/FlowRecordRepositoryImpl.java index 4a037968..25d9215a 100644 --- a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/repository/impl/FlowRecordRepositoryImpl.java +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/repository/impl/FlowRecordRepositoryImpl.java @@ -40,7 +40,7 @@ public void delete(FlowRecord flowRecord) { @Override public List findCurrentNodeRecords(long fromId, String nodeId) { - return flowRecordEntityRepository.findFlowRecordEntityByFromIdAndNodeIdAndRevoked(fromId, nodeId, false) + return flowRecordEntityRepository.findCurrentNodeRecords(fromId, nodeId) .stream() .map(FlowRecordConvertor::convert) .toList(); @@ -48,7 +48,7 @@ public List findCurrentNodeRecords(long fromId, String nodeId) { @Override public List findProcessRecords(String processId) { - return flowRecordEntityRepository.findFlowRecordEntityByProcessId(processId) + return flowRecordEntityRepository.findProcessIdRecords(processId) .stream() .map(FlowRecordConvertor::convert) .toList(); @@ -56,7 +56,7 @@ public List findProcessRecords(String processId) { @Override public List findTodoRecords(String processId) { - return flowRecordEntityRepository.findFlowRecordEntityByProcessIdAndRecordStateAndFlowStateAndHiddenAndRevoked(processId, FlowRecord.SATE_RECORD_TODO, FlowRecord.SATE_FLOW_RUNNING, false, false) + return flowRecordEntityRepository.findTodoRecords(processId) .stream() .map(FlowRecordConvertor::convert) .toList(); @@ -64,7 +64,7 @@ public List findTodoRecords(String processId) { @Override public List findAfterRecords(String processId, long fromId) { - return flowRecordEntityRepository.findFlowRecordEntityByProcessIdAndFromIdGreaterThanEqual(processId, fromId) + return flowRecordEntityRepository.findAfterRecords(processId, fromId) .stream() .map(FlowRecordConvertor::convert) .toList(); diff --git a/flow-engine-starter-query/src/main/java/com/codingapi/flow/query/controller/FlowRecordQueryController.java b/flow-engine-starter-query/src/main/java/com/codingapi/flow/query/controller/FlowRecordQueryController.java index 505c0614..1d896d07 100644 --- a/flow-engine-starter-query/src/main/java/com/codingapi/flow/query/controller/FlowRecordQueryController.java +++ b/flow-engine-starter-query/src/main/java/com/codingapi/flow/query/controller/FlowRecordQueryController.java @@ -35,7 +35,7 @@ public MultiResponse list(SearchRequest request) { public MultiResponse todo(SearchRequest request) { IFlowOperator current = (IFlowOperator) UserContext.getInstance().current(); PageRequest pageRequest = request.toPageRequest(FlowRecordEntity.class); - return MultiResponse.of(flowRecordEntityRepository.findTodoPage(current.getUserId(),pageRequest)); + return MultiResponse.of(flowRecordEntityRepository.findTodoRecordPage(current.getUserId(),pageRequest)); } @@ -46,6 +46,6 @@ public MultiResponse todo(SearchRequest request) { public MultiResponse done(SearchRequest request) { IFlowOperator current = (IFlowOperator) UserContext.getInstance().current(); PageRequest pageRequest = request.toPageRequest(FlowRecordEntity.class); - return MultiResponse.of(flowRecordEntityRepository.findDonePage(current.getUserId(),pageRequest)); + return MultiResponse.of(flowRecordEntityRepository.findDoneRecordPage(current.getUserId(),pageRequest)); } } From c01fddc2b5ed589aa4319c89be6733c543839a66 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 11 Feb 2026 21:43:28 +0800 Subject: [PATCH 4/6] #30 --- .../com/codingapi/flow/record/FlowRecord.java | 18 +++++++++++++++--- .../flow/service/FlowMergeableServiceTest.java | 6 ++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowRecord.java b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowRecord.java index 272b0107..45e282ce 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowRecord.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowRecord.java @@ -190,7 +190,7 @@ public class FlowRecord { private long timeoutTime; /** * 是否可合并 - * 合并的数据,相同的 {@link FlowRecord#currentOperatorId} {@link FlowRecord#workBackupId} {@link FlowRecord#nodeId}字段的数据合并到一条记录上,待办列表中只展示最新的一条记录和总数。 + * {@link FlowRecord#getMergeId()} */ private boolean mergeable; /** @@ -223,6 +223,18 @@ public class FlowRecord { */ private int parallelBranchTotal; + /** + * 数据合并的依据,当开启时值为固定值,否则为随机数据 + * 相同的 {@link FlowRecord#currentOperatorId} {@link FlowRecord#workBackupId} {@link FlowRecord#nodeId}字段的数据合并到一条记录上。 + */ + public String getMergeId() { + if (mergeable) { + return String.format("%s-%s-%s", currentOperatorId, workBackupId, nodeId); + } else { + return RandomUtils.generateStringId(); + } + } + public FlowRecord(FlowSession flowSession, int nodeOrder) { IFlowAction action = flowSession.getCurrentAction(); @@ -240,9 +252,9 @@ public FlowRecord(FlowSession flowSession, int nodeOrder) { this.createOperatorId = flowSession.getCreatedOperator().getUserId(); this.createOperatorName = flowSession.getCreatedOperator().getName(); // 是否转交之后的人来审批的判断 - if(currentOperator.equals(sourceOperator)){ + if (currentOperator.equals(sourceOperator)) { this.forwardOperatorId = 0; - }else { + } else { this.forwardOperatorId = sourceOperator.getUserId(); this.forwardOperatorName = sourceOperator.getName(); } diff --git a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java index 84ebbd20..6b727945 100644 --- a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java +++ b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java @@ -26,8 +26,10 @@ import com.codingapi.flow.workflow.WorkflowBuilder; import org.junit.jupiter.api.Test; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -133,6 +135,10 @@ void mergeableRecords() { assertEquals(count, bossRecordList.size()); assertEquals(count, bossRecordList.stream().filter(FlowRecord::isMergeable).toList().size()); + List mergeIdList = bossRecordList.stream().map(FlowRecord::getMergeId).toList(); + Set set = new HashSet<>(mergeIdList); + assertEquals(1,set.size()); + List bossActions = bossNode.actionManager().getActions(); From dd59b41a35dcb89b68f4cdaeff8be35b688e059c Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 12 Feb 2026 10:25:58 +0800 Subject: [PATCH 5/6] fix #30 --- .../flow/context/RepositoryHolderContext.java | 132 +++++++++++++++- .../com/codingapi/flow/record/FlowRecord.java | 13 +- .../codingapi/flow/record/FlowTodoMarge.java | 40 +++++ .../codingapi/flow/record/FlowTodoRecord.java | 143 ++++++++++++++++++ .../flow/repository/FlowRecordRepository.java | 1 + .../repository/FlowTodoMargeRepository.java | 15 ++ .../repository/FlowTodoRecordRepository.java | 17 +++ .../codingapi/flow/service/FlowService.java | 26 ++-- .../flow/service/impl/FlowActionService.java | 9 +- .../flow/service/impl/FlowCreateService.java | 14 +- .../flow/service/impl/FlowDetailService.java | 16 +- .../flow/service/impl/FlowRevokeService.java | 8 +- .../flow/service/impl/FlowUrgeService.java | 11 +- .../FlowTodoMargeRepositoryImpl.java | 41 +++++ .../FlowTodoRecordRepositoryImpl.java | 48 ++++++ .../service/FlowMergeableServiceTest.java | 35 +++-- .../flow/service/FlowParallelServiceTest.java | 4 +- .../flow/service/FlowSampleServiceTest.java | 4 +- 18 files changed, 518 insertions(+), 59 deletions(-) create mode 100644 flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoMarge.java create mode 100644 flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoRecord.java create mode 100644 flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoMargeRepository.java create mode 100644 flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoRecordRepository.java create mode 100644 flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoMargeRepositoryImpl.java create mode 100644 flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoRecordRepositoryImpl.java diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/context/RepositoryHolderContext.java b/flow-engine-framework/src/main/java/com/codingapi/flow/context/RepositoryHolderContext.java index 2730c415..eecf0e67 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/context/RepositoryHolderContext.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/context/RepositoryHolderContext.java @@ -5,6 +5,8 @@ import com.codingapi.flow.gateway.FlowOperatorGateway; import com.codingapi.flow.operator.IFlowOperator; import com.codingapi.flow.record.FlowRecord; +import com.codingapi.flow.record.FlowTodoRecord; +import com.codingapi.flow.record.FlowTodoMarge; import com.codingapi.flow.repository.*; import com.codingapi.flow.service.FlowService; import com.codingapi.flow.service.impl.FlowActionService; @@ -12,6 +14,7 @@ import com.codingapi.flow.session.FlowSession; import lombok.Getter; +import java.util.ArrayList; import java.util.List; public class RepositoryHolderContext { @@ -29,6 +32,10 @@ private RepositoryHolderContext() { @Getter private FlowRecordRepository flowRecordRepository; @Getter + private FlowTodoRecordRepository flowTodoRecordRepository; + @Getter + private FlowTodoMargeRepository flowTodoMargeRepository; + @Getter private FlowOperatorGateway flowOperatorGateway; @Getter private ParallelBranchRepository parallelBranchRepository; @@ -45,6 +52,8 @@ public boolean isRegistered() { && delayTaskRepository != null && workflowBackupRepository != null && flowRecordRepository != null + && flowTodoRecordRepository != null + && flowTodoMargeRepository != null && flowOperatorGateway != null && workflowRepository != null && urgeIntervalRepository != null; @@ -60,6 +69,8 @@ public void verify() { public void register(WorkflowRepository workflowRepository, WorkflowBackupRepository workflowBackupRepository, FlowRecordRepository flowRecordRepository, + FlowTodoRecordRepository flowTodoRecordRepository, + FlowTodoMargeRepository flowTodoMargeRepository, FlowOperatorGateway flowOperatorGateway, ParallelBranchRepository parallelBranchRepository, DelayTaskRepository delayTaskRepository, @@ -67,6 +78,8 @@ public void register(WorkflowRepository workflowRepository, this.workflowRepository = workflowRepository; this.workflowBackupRepository = workflowBackupRepository; this.flowRecordRepository = flowRecordRepository; + this.flowTodoRecordRepository = flowTodoRecordRepository; + this.flowTodoMargeRepository = flowTodoMargeRepository; this.flowOperatorGateway = flowOperatorGateway; this.parallelBranchRepository = parallelBranchRepository; this.delayTaskRepository = delayTaskRepository; @@ -97,10 +110,7 @@ public FlowDelayTriggerService createDelayTriggerService(DelayTask task) { */ public FlowActionService createFlowActionService(FlowSession flowSession) { this.verify(); - return new FlowActionService(flowSession.toActionRequest(), - flowOperatorGateway, - flowRecordRepository, - workflowBackupRepository); + return new FlowActionService(flowSession.toActionRequest()); } @@ -114,6 +124,8 @@ public FlowService createFlowService() { return new FlowService(workflowRepository, flowOperatorGateway, flowRecordRepository, + flowTodoRecordRepository, + flowTodoMargeRepository, workflowBackupRepository, parallelBranchRepository, delayTaskRepository, @@ -142,12 +154,15 @@ public void deleteDelayTask(DelayTask delayTask) { delayTaskRepository.delete(delayTask); } + public void saveRecords(List flowRecords) { - flowRecordRepository.saveAll(flowRecords); + FlowRecordRepositoryService flowRecordRepositoryService = new FlowRecordRepositoryService(flowRecords); + flowRecordRepositoryService.saveAll(); } public void saveRecord(FlowRecord flowRecord) { - flowRecordRepository.save(flowRecord); + FlowRecordRepositoryService flowRecordRepositoryService = new FlowRecordRepositoryService(flowRecord); + flowRecordRepositoryService.saveAll(); } public List findCurrentNodeRecords(long fromId, String nodeId) { @@ -179,4 +194,109 @@ public List findDelayTasks() { } + private static class FlowRecordRepositoryService { + + private final List flowRecords; + private final FlowTodoRecordRepository flowTodoRecordRepository; + private final FlowTodoMargeRepository flowTodoMargeRepository; + private final FlowRecordRepository flowRecordRepository; + + + public FlowRecordRepositoryService(List flowRecords) { + this.flowTodoRecordRepository = RepositoryHolderContext.getInstance().getFlowTodoRecordRepository(); + this.flowTodoMargeRepository = RepositoryHolderContext.getInstance().getFlowTodoMargeRepository(); + this.flowRecordRepository = RepositoryHolderContext.getInstance().getFlowRecordRepository(); + this.flowRecords = flowRecords; + } + + public FlowRecordRepositoryService(FlowRecord flowRecord) { + this.flowTodoRecordRepository = RepositoryHolderContext.getInstance().getFlowTodoRecordRepository(); + this.flowTodoMargeRepository = RepositoryHolderContext.getInstance().getFlowTodoMargeRepository(); + this.flowRecordRepository = RepositoryHolderContext.getInstance().getFlowRecordRepository(); + this.flowRecords = new ArrayList<>(); + this.flowRecords.add(flowRecord); + } + + + private void saveTodoMargeRecords() { + List flowTodoRecords = new ArrayList<>(); + for (FlowRecord flowRecord : flowRecords) { + if (flowRecord.isTodo()) { + FlowTodoRecord todoMargeRecord = null; + if (flowRecord.isMergeable()) { + todoMargeRecord = flowTodoRecordRepository.getByMageKey(flowRecord.getMergeKey()); + if (todoMargeRecord == null) { + todoMargeRecord = new FlowTodoRecord(flowRecord); + } else { + todoMargeRecord.update(flowRecord); + todoMargeRecord.addMargeCount(); + } + } else { + todoMargeRecord = new FlowTodoRecord(flowRecord); + } + flowTodoRecords.add(todoMargeRecord); + } + } + if (!flowTodoRecords.isEmpty()) { + flowTodoRecordRepository.saveAll(flowTodoRecords); + } + + if (!flowTodoRecords.isEmpty()) { + List relationList = new ArrayList<>(); + for (FlowTodoRecord margeRecord : flowTodoRecords) { + if(margeRecord.isMergeable()) { + relationList.add(new FlowTodoMarge(margeRecord)); + } + } + flowTodoMargeRepository.saveAll(relationList); + } + } + + private void saveRecords() { + if (!flowRecords.isEmpty()) { + flowRecordRepository.saveAll(flowRecords); + } + } + + + private void removeTodoMargeRecords() { + for (FlowRecord flowRecord : flowRecords) { + if (flowRecord.isDone()) { + if (flowRecord.isMergeable()) { + FlowTodoRecord todoMargeRecord = flowTodoRecordRepository.getByMageKey(flowRecord.getMergeKey()); + if(todoMargeRecord!=null) { + List margeRelations = flowTodoMargeRepository.findByTodoId(todoMargeRecord.getId()); + if(margeRelations!=null && !margeRelations.isEmpty()) { + for (FlowTodoMarge margeRelation : margeRelations) { + if (margeRelation.isRecord(flowRecord.getId())) { + flowTodoMargeRepository.remove(margeRelation); + todoMargeRecord.divMargeCount(); + if (todoMargeRecord.hasMargeCount()) { + flowTodoRecordRepository.save(todoMargeRecord); + } else { + flowTodoRecordRepository.remove(todoMargeRecord); + } + } + } + } + } + } else { + FlowTodoRecord todoMargeRecord = flowTodoRecordRepository.getByMageKey(flowRecord.getMergeKey()); + if (todoMargeRecord != null) { + flowTodoRecordRepository.remove(todoMargeRecord); + } + } + } + } + } + + public void saveAll() { + this.saveRecords(); + this.saveTodoMargeRecords(); + this.removeTodoMargeRecords(); + } + + + } + } diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowRecord.java b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowRecord.java index 45e282ce..519b7dfa 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowRecord.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowRecord.java @@ -190,7 +190,7 @@ public class FlowRecord { private long timeoutTime; /** * 是否可合并 - * {@link FlowRecord#getMergeId()} + * {@link FlowRecord#getMergeKey()} */ private boolean mergeable; /** @@ -227,11 +227,11 @@ public class FlowRecord { * 数据合并的依据,当开启时值为固定值,否则为随机数据 * 相同的 {@link FlowRecord#currentOperatorId} {@link FlowRecord#workBackupId} {@link FlowRecord#nodeId}字段的数据合并到一条记录上。 */ - public String getMergeId() { + public String getMergeKey() { if (mergeable) { return String.format("%s-%s-%s", currentOperatorId, workBackupId, nodeId); } else { - return RandomUtils.generateStringId(); + return String.valueOf(id); } } @@ -352,6 +352,13 @@ public boolean isTodo() { return recordState == SATE_RECORD_TODO && flowState == SATE_FLOW_RUNNING && !hidden && !revoked; } + /** + * 是否已办 + */ + public boolean isDone() { + return recordState == SATE_RECORD_DONE && !hidden && !revoked; + } + /** * 判断是否已完成 diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoMarge.java b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoMarge.java new file mode 100644 index 00000000..afcac132 --- /dev/null +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoMarge.java @@ -0,0 +1,40 @@ +package com.codingapi.flow.record; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +/** + * 存储待办合并的记录,仅当开启流程记录合并时才会产生合并记录数据 + * {@link FlowRecord#isMergeable()} 为true时才会产生 + */ +@Getter +@AllArgsConstructor +public class FlowTodoMarge { + + @Setter + private long id; + /** + * 待办id + */ + private long todoId; + /** + * 待办记录id + */ + private long recordId; + /** + * 创建时间 + */ + private long createTime; + + public FlowTodoMarge(FlowTodoRecord margeRecord){ + this.todoId = margeRecord.getId(); + this.recordId = margeRecord.getRecordId(); + this.createTime = margeRecord.getCreateTime(); + } + + + public boolean isRecord(long recordId) { + return this.recordId == recordId; + } +} diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoRecord.java b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoRecord.java new file mode 100644 index 00000000..5360e28c --- /dev/null +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoRecord.java @@ -0,0 +1,143 @@ +package com.codingapi.flow.record; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +/** + * 待办记录数据,所有的待办列表 + */ +@Getter +@AllArgsConstructor +public class FlowTodoRecord { + + /** + * 合并记录id + */ + @Setter + private long id; + + /** + * 流程id + * 每一次流程启动时生成,直到流程结束 + */ + private String processId; + + /** + * 工作id + */ + private long workBackupId; + /** + * 流程编码 + */ + private String workCode; + /** + * 节点id + */ + private String nodeId; + /** + * 节点类型 + */ + private String nodeType; + + /** + * 消息标题 + */ + private String title; + /** + * 读取时间 + */ + private long readTime; + + /** + * 当前审批人Id + */ + private long currentOperatorId; + + /** + * 当前审批人名称 + */ + private String currentOperatorName; + + /** + * 创建时间 + */ + private long createTime; + + /** + * 发起者id + */ + private long createOperatorId; + /** + * 发起者名称 + */ + private String createOperatorName; + + /** + * 合并记录id,当存在合并记录数据时待办记录数量不会增加,内容会更新至最新的待办数据信息。 + * {@link FlowRecord#getMergeKey()} + */ + private String margeKey; + + /** + * 合并记录数量 + */ + private int margeCount; + + /** + * 是否可合并 + */ + private boolean mergeable; + + /** + * 待办记录id + */ + private long recordId; + + /** + * 超时到期时间 + */ + private long timeoutTime; + + + public FlowTodoRecord(FlowRecord flowRecord) { + this.update(flowRecord); + } + + + public void update(FlowRecord flowRecord){ + this.processId = flowRecord.getProcessId(); + this.workBackupId = flowRecord.getWorkBackupId(); + this.workCode = flowRecord.getWorkCode(); + this.nodeId = flowRecord.getNodeId(); + this.nodeType = flowRecord.getNodeType(); + this.title = flowRecord.getTitle(); + this.readTime = flowRecord.getReadTime(); + this.currentOperatorId = flowRecord.getCurrentOperatorId(); + this.currentOperatorName = flowRecord.getCurrentOperatorName(); + this.createTime = flowRecord.getCreateTime(); + this.createOperatorId = flowRecord.getCreateOperatorId(); + this.createOperatorName = flowRecord.getCreateOperatorName(); + this.margeKey = flowRecord.getMergeKey(); + this.mergeable = flowRecord.isMergeable(); + this.recordId = flowRecord.getId(); + this.timeoutTime = flowRecord.getTimeoutTime(); + } + + public void addMargeCount(){ + if(this.mergeable) { + this.margeCount++; + } + } + + public void divMargeCount(){ + if(this.mergeable) { + this.margeCount--; + } + } + + public boolean hasMargeCount(){ + return this.mergeable && this.margeCount > 0; + } + +} diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowRecordRepository.java b/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowRecordRepository.java index 473be5ff..8c6ae3ab 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowRecordRepository.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowRecordRepository.java @@ -18,6 +18,7 @@ public interface FlowRecordRepository { /** * 保存流程 + * 为何确保待办合并数据的一致性,保存流程需要通过 {@link com.codingapi.flow.context.RepositoryHolderContext#saveRecord(FlowRecord)} 保存 * @param flowRecord 流程记录 */ void save(FlowRecord flowRecord); diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoMargeRepository.java b/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoMargeRepository.java new file mode 100644 index 00000000..778af68a --- /dev/null +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoMargeRepository.java @@ -0,0 +1,15 @@ +package com.codingapi.flow.repository; + +import com.codingapi.flow.record.FlowTodoMarge; + +import java.util.List; + +public interface FlowTodoMargeRepository { + + void saveAll(List relations); + + void remove(FlowTodoMarge relation); + + List findByTodoId(long todoId); + +} diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoRecordRepository.java b/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoRecordRepository.java new file mode 100644 index 00000000..e790f500 --- /dev/null +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoRecordRepository.java @@ -0,0 +1,17 @@ +package com.codingapi.flow.repository; + +import com.codingapi.flow.record.FlowTodoRecord; + +import java.util.List; + +public interface FlowTodoRecordRepository { + + void saveAll(List margeRecords); + + FlowTodoRecord getByMageKey(String key); + + void remove(FlowTodoRecord margeRecord); + + void save(FlowTodoRecord margeRecord); + +} diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/service/FlowService.java b/flow-engine-framework/src/main/java/com/codingapi/flow/service/FlowService.java index fc83b1be..8bbcb7bf 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/service/FlowService.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/service/FlowService.java @@ -16,29 +16,21 @@ */ public class FlowService { - private final WorkflowRepository workflowRepository; - private final FlowOperatorGateway flowOperatorGateway; - private final FlowRecordRepository flowRecordRepository; - private final WorkflowBackupRepository workflowBackupRepository; - private final UrgeIntervalRepository urgeIntervalRepository; - public FlowService(WorkflowRepository workflowRepository, FlowOperatorGateway flowOperatorGateway, FlowRecordRepository flowRecordRepository, + FlowTodoRecordRepository flowTodoRecordRepository, + FlowTodoMargeRepository flowTodoMargeRepository, WorkflowBackupRepository workflowBackupRepository, ParallelBranchRepository parallelBranchRepository, DelayTaskRepository delayTaskRepository, UrgeIntervalRepository urgeIntervalRepository) { - this.workflowRepository = workflowRepository; - this.flowOperatorGateway = flowOperatorGateway; - this.flowRecordRepository = flowRecordRepository; - this.workflowBackupRepository = workflowBackupRepository; - this.urgeIntervalRepository = urgeIntervalRepository; - RepositoryHolderContext.getInstance() .register(workflowRepository, workflowBackupRepository, flowRecordRepository, + flowTodoRecordRepository, + flowTodoMargeRepository, flowOperatorGateway, parallelBranchRepository, delayTaskRepository, @@ -52,7 +44,7 @@ public FlowService(WorkflowRepository workflowRepository, * @return 流程详情 */ public FlowContent detail(String id,IFlowOperator currentOperator) { - FlowDetailService flowDetailService = new FlowDetailService(id,currentOperator,flowRecordRepository, flowOperatorGateway,workflowRepository, workflowBackupRepository); + FlowDetailService flowDetailService = new FlowDetailService(id,currentOperator); return flowDetailService.detail(); } @@ -63,7 +55,7 @@ public FlowContent detail(String id,IFlowOperator currentOperator) { * @return 创建的流程id */ public long create(FlowCreateRequest request) { - FlowCreateService flowCreateService = new FlowCreateService(request, flowOperatorGateway, flowRecordRepository, workflowRepository, workflowBackupRepository); + FlowCreateService flowCreateService = new FlowCreateService(request); return flowCreateService.create(); } @@ -73,7 +65,7 @@ public long create(FlowCreateRequest request) { * @param request 审批请求 */ public void action(FlowActionRequest request) { - FlowActionService flowActionService = new FlowActionService(request, flowOperatorGateway, flowRecordRepository, workflowBackupRepository); + FlowActionService flowActionService = new FlowActionService(request); flowActionService.action(); } @@ -83,7 +75,7 @@ public void action(FlowActionRequest request) { * @param request 撤销请求 */ public void revoke(FlowRevokeRequest request) { - FlowRevokeService flowRevokeService = new FlowRevokeService(request, flowRecordRepository, workflowBackupRepository); + FlowRevokeService flowRevokeService = new FlowRevokeService(request); flowRevokeService.revoke(); } @@ -92,7 +84,7 @@ public void revoke(FlowRevokeRequest request) { * 催办 */ public void urge(FlowUrgeRequest request) { - FlowUrgeService flowUrgeService = new FlowUrgeService(request, flowRecordRepository, flowOperatorGateway, urgeIntervalRepository, workflowBackupRepository); + FlowUrgeService flowUrgeService = new FlowUrgeService(request); flowUrgeService.urge(); } } diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowActionService.java b/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowActionService.java index 71c3dbaa..451a50e5 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowActionService.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowActionService.java @@ -17,14 +17,12 @@ import com.codingapi.flow.session.FlowAdvice; import com.codingapi.flow.session.FlowSession; import com.codingapi.flow.workflow.Workflow; -import lombok.AllArgsConstructor; import java.util.List; /** * 节点动作服务 */ -@AllArgsConstructor public class FlowActionService { private final FlowActionRequest request; @@ -32,6 +30,13 @@ public class FlowActionService { private final FlowRecordRepository flowRecordRepository; private final WorkflowBackupRepository workflowBackupRepository; + public FlowActionService(FlowActionRequest request) { + this.request = request; + this.flowOperatorGateway = RepositoryHolderContext.getInstance().getFlowOperatorGateway(); + this.flowRecordRepository = RepositoryHolderContext.getInstance().getFlowRecordRepository(); + this.workflowBackupRepository = RepositoryHolderContext.getInstance().getWorkflowBackupRepository(); + } + public void action() { request.verify(); diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowCreateService.java b/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowCreateService.java index 30092672..63290255 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowCreateService.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowCreateService.java @@ -2,6 +2,7 @@ import com.codingapi.flow.action.IFlowAction; import com.codingapi.flow.backup.WorkflowBackup; +import com.codingapi.flow.context.RepositoryHolderContext; import com.codingapi.flow.event.FlowRecordStartEvent; import com.codingapi.flow.event.FlowRecordTodoEvent; import com.codingapi.flow.event.IFlowEvent; @@ -15,13 +16,11 @@ import com.codingapi.flow.operator.IFlowOperator; import com.codingapi.flow.pojo.request.FlowCreateRequest; import com.codingapi.flow.record.FlowRecord; -import com.codingapi.flow.repository.FlowRecordRepository; import com.codingapi.flow.repository.WorkflowBackupRepository; import com.codingapi.flow.repository.WorkflowRepository; import com.codingapi.flow.session.FlowSession; import com.codingapi.flow.workflow.Workflow; import com.codingapi.springboot.framework.event.EventPusher; -import lombok.AllArgsConstructor; import java.util.ArrayList; import java.util.List; @@ -29,15 +28,20 @@ /** * 创建流程服务 */ -@AllArgsConstructor public class FlowCreateService { private final FlowCreateRequest request; private final FlowOperatorGateway flowOperatorGateway; - private final FlowRecordRepository flowRecordRepository; private final WorkflowRepository workflowRepository; private final WorkflowBackupRepository workflowBackupRepository; + public FlowCreateService(FlowCreateRequest request) { + this.request = request; + this.flowOperatorGateway = RepositoryHolderContext.getInstance().getFlowOperatorGateway(); + this.workflowRepository = RepositoryHolderContext.getInstance().getWorkflowRepository(); + this.workflowBackupRepository = RepositoryHolderContext.getInstance().getWorkflowBackupRepository(); + } + public long create() { request.verify(); Workflow workflow = workflowRepository.get(request.getWorkId()); @@ -75,7 +79,7 @@ public long create() { throw FlowExecutionException.createRecordSizeError(); } - flowRecordRepository.saveAll(flowRecords); + RepositoryHolderContext.getInstance().saveRecords(flowRecords); List events = new ArrayList<>(); for (FlowRecord flowRecord : flowRecords) { diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowDetailService.java b/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowDetailService.java index d84aee03..7751f40d 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowDetailService.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowDetailService.java @@ -1,6 +1,7 @@ package com.codingapi.flow.service.impl; import com.codingapi.flow.backup.WorkflowBackup; +import com.codingapi.flow.context.RepositoryHolderContext; import com.codingapi.flow.exception.FlowNotFoundException; import com.codingapi.flow.gateway.FlowOperatorGateway; import com.codingapi.flow.operator.IFlowOperator; @@ -21,18 +22,13 @@ public class FlowDetailService { private final WorkflowRepository workflowRepository; private final WorkflowBackupRepository workflowBackupRepository; - public FlowDetailService(String id, - IFlowOperator currentOperator, - FlowRecordRepository flowRecordRepository, - FlowOperatorGateway flowOperatorGateway, - WorkflowRepository workflowRepository, - WorkflowBackupRepository workflowBackupRepository) { + public FlowDetailService(String id, IFlowOperator currentOperator) { this.id = id; this.currentOperator = currentOperator; - this.flowRecordRepository = flowRecordRepository; - this.flowOperatorGateway = flowOperatorGateway; - this.workflowRepository = workflowRepository; - this.workflowBackupRepository = workflowBackupRepository; + this.flowRecordRepository = RepositoryHolderContext.getInstance().getFlowRecordRepository(); + this.flowOperatorGateway = RepositoryHolderContext.getInstance().getFlowOperatorGateway(); + this.workflowRepository = RepositoryHolderContext.getInstance().getWorkflowRepository(); + this.workflowBackupRepository = RepositoryHolderContext.getInstance().getWorkflowBackupRepository(); } diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowRevokeService.java b/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowRevokeService.java index d9390c1c..c1b47ba3 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowRevokeService.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowRevokeService.java @@ -15,7 +15,6 @@ import com.codingapi.flow.strategy.node.RevokeStrategy; import com.codingapi.flow.workflow.Workflow; import com.codingapi.springboot.framework.event.EventPusher; -import lombok.AllArgsConstructor; import java.util.ArrayList; import java.util.List; @@ -23,13 +22,18 @@ /** * 撤销流程服务 */ -@AllArgsConstructor public class FlowRevokeService { private final FlowRevokeRequest request; private final FlowRecordRepository flowRecordRepository; private final WorkflowBackupRepository workflowBackupRepository; + public FlowRevokeService(FlowRevokeRequest request) { + this.request = request; + this.flowRecordRepository = RepositoryHolderContext.getInstance().getFlowRecordRepository(); + this.workflowBackupRepository = RepositoryHolderContext.getInstance().getWorkflowBackupRepository(); + } + public void revoke() { request.verify(); // 验证当前用户 diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowUrgeService.java b/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowUrgeService.java index 7a1263ff..016b0049 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowUrgeService.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowUrgeService.java @@ -1,6 +1,7 @@ package com.codingapi.flow.service.impl; import com.codingapi.flow.backup.WorkflowBackup; +import com.codingapi.flow.context.RepositoryHolderContext; import com.codingapi.flow.domain.UrgeInterval; import com.codingapi.flow.event.FlowRecordUrgeEvent; import com.codingapi.flow.event.IFlowEvent; @@ -17,7 +18,6 @@ import com.codingapi.flow.strategy.workflow.UrgeStrategy; import com.codingapi.flow.workflow.Workflow; import com.codingapi.springboot.framework.event.EventPusher; -import lombok.AllArgsConstructor; import java.util.ArrayList; import java.util.List; @@ -25,7 +25,6 @@ /** * 催办服务 */ -@AllArgsConstructor public class FlowUrgeService { private final FlowUrgeRequest request; @@ -34,6 +33,14 @@ public class FlowUrgeService { private final UrgeIntervalRepository urgeIntervalRepository; private final WorkflowBackupRepository workflowBackupRepository; + public FlowUrgeService(FlowUrgeRequest request) { + this.request = request; + this.flowRecordRepository = RepositoryHolderContext.getInstance().getFlowRecordRepository(); + this.flowOperatorGateway = RepositoryHolderContext.getInstance().getFlowOperatorGateway(); + this.urgeIntervalRepository = RepositoryHolderContext.getInstance().getUrgeIntervalRepository(); + this.workflowBackupRepository = RepositoryHolderContext.getInstance().getWorkflowBackupRepository(); + } + /** * 催办 */ diff --git a/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoMargeRepositoryImpl.java b/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoMargeRepositoryImpl.java new file mode 100644 index 00000000..ef8df962 --- /dev/null +++ b/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoMargeRepositoryImpl.java @@ -0,0 +1,41 @@ +package com.codingapi.flow.repository; + +import com.codingapi.flow.record.FlowTodoMarge; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class FlowTodoMargeRepositoryImpl implements FlowTodoMargeRepository { + + private final Map cache = new HashMap<>(); + + private void save(FlowTodoMarge relation) { + if (relation.getId() > 0) { + cache.put(relation.getId(), relation); + } else { + long id = cache.size() + 1; + relation.setId(id); + cache.put(id, relation); + } + } + + @Override + public void remove(FlowTodoMarge relation) { + this.cache.remove(relation.getId()); + } + + @Override + public void saveAll(List relations) { + for (FlowTodoMarge relation : relations){ + this.save(relation); + } + } + + @Override + public List findByTodoId(long todoId) { + return cache.values().stream(). + filter(relation -> relation.getTodoId() == todoId) + .toList(); + } +} diff --git a/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoRecordRepositoryImpl.java b/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoRecordRepositoryImpl.java new file mode 100644 index 00000000..8c95fc08 --- /dev/null +++ b/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoRecordRepositoryImpl.java @@ -0,0 +1,48 @@ +package com.codingapi.flow.repository; + +import com.codingapi.flow.record.FlowTodoRecord; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class FlowTodoRecordRepositoryImpl implements FlowTodoRecordRepository { + + private final Map cache = new HashMap<>(); + private final Map cacheByMageKey = new HashMap<>(); + + @Override + public void save(FlowTodoRecord record) { + if (record.getId() > 0) { + cache.put(record.getId(), record); + } else { + long id = cache.size() + 1; + record.setId(id); + cache.put(id, record); + } + cacheByMageKey.put(record.getMargeKey(), record); + } + + @Override + public void saveAll(List margeRecords) { + for (FlowTodoRecord record : margeRecords){ + this.save(record); + } + } + + @Override + public void remove(FlowTodoRecord margeRecord) { + cacheByMageKey.remove(margeRecord.getMargeKey()); + cache.remove(margeRecord.getId()); + } + + @Override + public FlowTodoRecord getByMageKey(String key) { + return cacheByMageKey.get(key); + } + + public List findByOperatorId(long operatorId) { + return cache.values().stream().filter(record -> record.getCurrentOperatorId() == operatorId).toList(); + } + +} diff --git a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java index 6b727945..55089d7c 100644 --- a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java +++ b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java @@ -17,6 +17,8 @@ import com.codingapi.flow.pojo.request.FlowActionRequest; import com.codingapi.flow.pojo.request.FlowCreateRequest; import com.codingapi.flow.record.FlowRecord; +import com.codingapi.flow.record.FlowTodoRecord; +import com.codingapi.flow.record.FlowTodoMarge; import com.codingapi.flow.repository.*; import com.codingapi.flow.strategy.node.FormFieldPermissionStrategy; import com.codingapi.flow.strategy.node.OperatorLoadStrategy; @@ -35,6 +37,8 @@ public class FlowMergeableServiceTest { + private final FlowTodoRecordRepositoryImpl flowTodoMargeRecordRepository = new FlowTodoRecordRepositoryImpl(); + private final FlowTodoMargeRepositoryImpl flowTodoMargeRelationRepository = new FlowTodoMargeRepositoryImpl(); private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); private final UserGateway userGateway = new UserGateway(); private final WorkflowBackupRepository workflowBackupRepository = new WorkflowBackupRepositoryImpl(); @@ -42,7 +46,7 @@ public class FlowMergeableServiceTest { private final ParallelBranchRepository parallelBranchRepository = new ParallelBranchRepositoryImpl(); private final DelayTaskRepository delayTaskRepository = new DelayTaskRepositoryImpl(); private final UrgeIntervalRepository urgeIntervalRepository = new UrgeIntervalRepositoryImpl(); - private final FlowService flowService = new FlowService(workflowRepository, userGateway, flowRecordRepository, workflowBackupRepository, parallelBranchRepository, delayTaskRepository, urgeIntervalRepository); + private final FlowService flowService = new FlowService(workflowRepository, userGateway, flowRecordRepository,flowTodoMargeRecordRepository,flowTodoMargeRelationRepository, workflowBackupRepository, parallelBranchRepository, delayTaskRepository, urgeIntervalRepository); /** @@ -135,22 +139,33 @@ void mergeableRecords() { assertEquals(count, bossRecordList.size()); assertEquals(count, bossRecordList.stream().filter(FlowRecord::isMergeable).toList().size()); - List mergeIdList = bossRecordList.stream().map(FlowRecord::getMergeId).toList(); + List mergeIdList = bossRecordList.stream().map(FlowRecord::getMergeKey).toList(); Set set = new HashSet<>(mergeIdList); assertEquals(1,set.size()); + List todoMargeRecords = flowTodoMargeRecordRepository.findByOperatorId(boss.getUserId()); + assertEquals(1, todoMargeRecords.size()); + + FlowTodoRecord todoMargeRecord = todoMargeRecords.get(0); + List relationList = flowTodoMargeRelationRepository.findByTodoId(todoMargeRecord.getId()); + assertEquals(count, relationList.size()); + List bossActions = bossNode.actionManager().getActions(); - FlowActionRequest bossRequest = new FlowActionRequest(); - bossRequest.setFormData(data); - bossRequest.setRecordId(bossRecordList.get(0).getId()); - bossRequest.setAdvice(new FlowAdviceBody(bossActions.get(0).id(), "同意", boss.getUserId())); - flowService.action(bossRequest); + for(int i=0;i records = flowRecordRepository.findProcessRecords(bossRecordList.get(0).getProcessId()); - assertEquals(3, records.size()); - assertEquals(3, records.stream().filter(FlowRecord::isFinish).toList().size()); + for(int i=0;i records = flowRecordRepository.findProcessRecords(bossRecordList.get(i).getProcessId()); + assertEquals(3, records.size()); + assertEquals(3, records.stream().filter(FlowRecord::isFinish).toList().size()); + } } } diff --git a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowParallelServiceTest.java b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowParallelServiceTest.java index 39f971c7..810981e7 100644 --- a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowParallelServiceTest.java +++ b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowParallelServiceTest.java @@ -29,6 +29,8 @@ class FlowParallelServiceTest { + private final FlowTodoRecordRepositoryImpl flowTodoMargeRecordRepository = new FlowTodoRecordRepositoryImpl(); + private final FlowTodoMargeRepositoryImpl flowTodoMargeRelationRepository = new FlowTodoMargeRepositoryImpl(); private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); private final UserGateway userGateway = new UserGateway(); private final WorkflowBackupRepository workflowBackupRepository = new WorkflowBackupRepositoryImpl(); @@ -36,7 +38,7 @@ class FlowParallelServiceTest { private final ParallelBranchRepository parallelBranchRepository = new ParallelBranchRepositoryImpl(); private final DelayTaskRepository delayTaskRepository = new DelayTaskRepositoryImpl(); private final UrgeIntervalRepository urgeIntervalRepository = new UrgeIntervalRepositoryImpl(); - private final FlowService flowService = new FlowService(workflowRepository, userGateway, flowRecordRepository, workflowBackupRepository, parallelBranchRepository, delayTaskRepository, urgeIntervalRepository); + private final FlowService flowService = new FlowService(workflowRepository, userGateway, flowRecordRepository,flowTodoMargeRecordRepository,flowTodoMargeRelationRepository, workflowBackupRepository, parallelBranchRepository, delayTaskRepository, urgeIntervalRepository); /** diff --git a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowSampleServiceTest.java b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowSampleServiceTest.java index dfe33a60..57a5e696 100644 --- a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowSampleServiceTest.java +++ b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowSampleServiceTest.java @@ -37,6 +37,8 @@ class FlowSampleServiceTest { + private final FlowTodoRecordRepositoryImpl flowTodoMargeRecordRepository = new FlowTodoRecordRepositoryImpl(); + private final FlowTodoMargeRepositoryImpl flowTodoMargeRelationRepository = new FlowTodoMargeRepositoryImpl(); private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); private final UserGateway userGateway = new UserGateway(); private final WorkflowBackupRepository workflowBackupRepository = new WorkflowBackupRepositoryImpl(); @@ -44,7 +46,7 @@ class FlowSampleServiceTest { private final ParallelBranchRepository parallelBranchRepository = new ParallelBranchRepositoryImpl(); private final DelayTaskRepository delayTaskRepository = new DelayTaskRepositoryImpl(); private final UrgeIntervalRepository urgeIntervalRepository = new UrgeIntervalRepositoryImpl(); - private final FlowService flowService = new FlowService(workflowRepository, userGateway, flowRecordRepository, workflowBackupRepository, parallelBranchRepository, delayTaskRepository, urgeIntervalRepository); + private final FlowService flowService = new FlowService(workflowRepository, userGateway, flowRecordRepository,flowTodoMargeRecordRepository,flowTodoMargeRelationRepository, workflowBackupRepository, parallelBranchRepository, delayTaskRepository, urgeIntervalRepository); @Test void create() { From 63c7c67f1a030d32f9686e475d73bda80e1fd963 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Thu, 12 Feb 2026 11:10:31 +0800 Subject: [PATCH 6/6] fix #30 --- .../flow/context/RepositoryHolderContext.java | 36 ++-- ...{FlowTodoMarge.java => FlowTodoMerge.java} | 4 +- .../codingapi/flow/record/FlowTodoRecord.java | 4 +- .../repository/FlowTodoMargeRepository.java | 15 -- .../repository/FlowTodoMergeRepository.java | 15 ++ .../repository/FlowTodoRecordRepository.java | 2 +- .../codingapi/flow/service/FlowService.java | 4 +- ....java => FlowTodoMergeRepositoryImpl.java} | 18 +- .../FlowTodoRecordRepositoryImpl.java | 6 +- .../service/FlowMergeableServiceTest.java | 6 +- .../flow/service/FlowParallelServiceTest.java | 2 +- .../flow/service/FlowSampleServiceTest.java | 2 +- .../flow/infra/AutoConfiguration.java | 10 ++ .../infra/convert/FlowTodoMargeConvertor.java | 31 ++++ .../convert/FlowTodoRecordConvertor.java | 61 +++++++ .../infra/entity/FlowTodoMargeEntity.java | 26 +++ .../infra/entity/FlowTodoRecordEntity.java | 100 +++++++++++ .../infra/jpa/FlowRecordEntityRepository.java | 3 + .../jpa/FlowTodoMargeEntityRepository.java | 11 ++ .../jpa/FlowTodoRecordEntityRepository.java | 16 ++ .../flow/infra/pojo/FlowRecordContent.java | 156 ++++++++++++++++++ .../impl/FlowTodoMergeRepositoryImpl.java | 40 +++++ .../impl/FlowTodoRecordRepositoryImpl.java | 40 +++++ .../controller/FlowRecordQueryController.java | 31 +++- .../com/codingapi/flow/AutoConfiguration.java | 8 + .../RepositoryHolderContextRegister.java | 4 + 26 files changed, 588 insertions(+), 63 deletions(-) rename flow-engine-framework/src/main/java/com/codingapi/flow/record/{FlowTodoMarge.java => FlowTodoMerge.java} (90%) delete mode 100644 flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoMargeRepository.java create mode 100644 flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoMergeRepository.java rename flow-engine-framework/src/test/java/com/codingapi/flow/repository/{FlowTodoMargeRepositoryImpl.java => FlowTodoMergeRepositoryImpl.java} (55%) create mode 100644 flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/convert/FlowTodoMargeConvertor.java create mode 100644 flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/convert/FlowTodoRecordConvertor.java create mode 100644 flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/entity/FlowTodoMargeEntity.java create mode 100644 flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/entity/FlowTodoRecordEntity.java create mode 100644 flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowTodoMargeEntityRepository.java create mode 100644 flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowTodoRecordEntityRepository.java create mode 100644 flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/pojo/FlowRecordContent.java create mode 100644 flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/repository/impl/FlowTodoMergeRepositoryImpl.java create mode 100644 flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/repository/impl/FlowTodoRecordRepositoryImpl.java diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/context/RepositoryHolderContext.java b/flow-engine-framework/src/main/java/com/codingapi/flow/context/RepositoryHolderContext.java index eecf0e67..5545add1 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/context/RepositoryHolderContext.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/context/RepositoryHolderContext.java @@ -6,7 +6,7 @@ import com.codingapi.flow.operator.IFlowOperator; import com.codingapi.flow.record.FlowRecord; import com.codingapi.flow.record.FlowTodoRecord; -import com.codingapi.flow.record.FlowTodoMarge; +import com.codingapi.flow.record.FlowTodoMerge; import com.codingapi.flow.repository.*; import com.codingapi.flow.service.FlowService; import com.codingapi.flow.service.impl.FlowActionService; @@ -34,7 +34,7 @@ private RepositoryHolderContext() { @Getter private FlowTodoRecordRepository flowTodoRecordRepository; @Getter - private FlowTodoMargeRepository flowTodoMargeRepository; + private FlowTodoMergeRepository flowTodoMergeRepository; @Getter private FlowOperatorGateway flowOperatorGateway; @Getter @@ -53,7 +53,7 @@ public boolean isRegistered() { && workflowBackupRepository != null && flowRecordRepository != null && flowTodoRecordRepository != null - && flowTodoMargeRepository != null + && flowTodoMergeRepository != null && flowOperatorGateway != null && workflowRepository != null && urgeIntervalRepository != null; @@ -70,7 +70,7 @@ public void register(WorkflowRepository workflowRepository, WorkflowBackupRepository workflowBackupRepository, FlowRecordRepository flowRecordRepository, FlowTodoRecordRepository flowTodoRecordRepository, - FlowTodoMargeRepository flowTodoMargeRepository, + FlowTodoMergeRepository flowTodoMergeRepository, FlowOperatorGateway flowOperatorGateway, ParallelBranchRepository parallelBranchRepository, DelayTaskRepository delayTaskRepository, @@ -79,7 +79,7 @@ public void register(WorkflowRepository workflowRepository, this.workflowBackupRepository = workflowBackupRepository; this.flowRecordRepository = flowRecordRepository; this.flowTodoRecordRepository = flowTodoRecordRepository; - this.flowTodoMargeRepository = flowTodoMargeRepository; + this.flowTodoMergeRepository = flowTodoMergeRepository; this.flowOperatorGateway = flowOperatorGateway; this.parallelBranchRepository = parallelBranchRepository; this.delayTaskRepository = delayTaskRepository; @@ -125,7 +125,7 @@ public FlowService createFlowService() { flowOperatorGateway, flowRecordRepository, flowTodoRecordRepository, - flowTodoMargeRepository, + flowTodoMergeRepository, workflowBackupRepository, parallelBranchRepository, delayTaskRepository, @@ -198,20 +198,20 @@ private static class FlowRecordRepositoryService { private final List flowRecords; private final FlowTodoRecordRepository flowTodoRecordRepository; - private final FlowTodoMargeRepository flowTodoMargeRepository; + private final FlowTodoMergeRepository flowTodoMergeRepository; private final FlowRecordRepository flowRecordRepository; public FlowRecordRepositoryService(List flowRecords) { this.flowTodoRecordRepository = RepositoryHolderContext.getInstance().getFlowTodoRecordRepository(); - this.flowTodoMargeRepository = RepositoryHolderContext.getInstance().getFlowTodoMargeRepository(); + this.flowTodoMergeRepository = RepositoryHolderContext.getInstance().getFlowTodoMergeRepository(); this.flowRecordRepository = RepositoryHolderContext.getInstance().getFlowRecordRepository(); this.flowRecords = flowRecords; } public FlowRecordRepositoryService(FlowRecord flowRecord) { this.flowTodoRecordRepository = RepositoryHolderContext.getInstance().getFlowTodoRecordRepository(); - this.flowTodoMargeRepository = RepositoryHolderContext.getInstance().getFlowTodoMargeRepository(); + this.flowTodoMergeRepository = RepositoryHolderContext.getInstance().getFlowTodoMergeRepository(); this.flowRecordRepository = RepositoryHolderContext.getInstance().getFlowRecordRepository(); this.flowRecords = new ArrayList<>(); this.flowRecords.add(flowRecord); @@ -224,7 +224,7 @@ private void saveTodoMargeRecords() { if (flowRecord.isTodo()) { FlowTodoRecord todoMargeRecord = null; if (flowRecord.isMergeable()) { - todoMargeRecord = flowTodoRecordRepository.getByMageKey(flowRecord.getMergeKey()); + todoMargeRecord = flowTodoRecordRepository.getByMergeKey(flowRecord.getMergeKey()); if (todoMargeRecord == null) { todoMargeRecord = new FlowTodoRecord(flowRecord); } else { @@ -242,13 +242,13 @@ private void saveTodoMargeRecords() { } if (!flowTodoRecords.isEmpty()) { - List relationList = new ArrayList<>(); + List relationList = new ArrayList<>(); for (FlowTodoRecord margeRecord : flowTodoRecords) { if(margeRecord.isMergeable()) { - relationList.add(new FlowTodoMarge(margeRecord)); + relationList.add(new FlowTodoMerge(margeRecord)); } } - flowTodoMargeRepository.saveAll(relationList); + flowTodoMergeRepository.saveAll(relationList); } } @@ -263,13 +263,13 @@ private void removeTodoMargeRecords() { for (FlowRecord flowRecord : flowRecords) { if (flowRecord.isDone()) { if (flowRecord.isMergeable()) { - FlowTodoRecord todoMargeRecord = flowTodoRecordRepository.getByMageKey(flowRecord.getMergeKey()); + FlowTodoRecord todoMargeRecord = flowTodoRecordRepository.getByMergeKey(flowRecord.getMergeKey()); if(todoMargeRecord!=null) { - List margeRelations = flowTodoMargeRepository.findByTodoId(todoMargeRecord.getId()); + List margeRelations = flowTodoMergeRepository.findByTodoId(todoMargeRecord.getId()); if(margeRelations!=null && !margeRelations.isEmpty()) { - for (FlowTodoMarge margeRelation : margeRelations) { + for (FlowTodoMerge margeRelation : margeRelations) { if (margeRelation.isRecord(flowRecord.getId())) { - flowTodoMargeRepository.remove(margeRelation); + flowTodoMergeRepository.remove(margeRelation); todoMargeRecord.divMargeCount(); if (todoMargeRecord.hasMargeCount()) { flowTodoRecordRepository.save(todoMargeRecord); @@ -281,7 +281,7 @@ private void removeTodoMargeRecords() { } } } else { - FlowTodoRecord todoMargeRecord = flowTodoRecordRepository.getByMageKey(flowRecord.getMergeKey()); + FlowTodoRecord todoMargeRecord = flowTodoRecordRepository.getByMergeKey(flowRecord.getMergeKey()); if (todoMargeRecord != null) { flowTodoRecordRepository.remove(todoMargeRecord); } diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoMarge.java b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoMerge.java similarity index 90% rename from flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoMarge.java rename to flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoMerge.java index afcac132..5940a624 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoMarge.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoMerge.java @@ -10,7 +10,7 @@ */ @Getter @AllArgsConstructor -public class FlowTodoMarge { +public class FlowTodoMerge { @Setter private long id; @@ -27,7 +27,7 @@ public class FlowTodoMarge { */ private long createTime; - public FlowTodoMarge(FlowTodoRecord margeRecord){ + public FlowTodoMerge(FlowTodoRecord margeRecord){ this.todoId = margeRecord.getId(); this.recordId = margeRecord.getRecordId(); this.createTime = margeRecord.getCreateTime(); diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoRecord.java b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoRecord.java index 5360e28c..074c10b8 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoRecord.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/record/FlowTodoRecord.java @@ -77,7 +77,7 @@ public class FlowTodoRecord { * 合并记录id,当存在合并记录数据时待办记录数量不会增加,内容会更新至最新的待办数据信息。 * {@link FlowRecord#getMergeKey()} */ - private String margeKey; + private String mergeKey; /** * 合并记录数量 @@ -118,7 +118,7 @@ public void update(FlowRecord flowRecord){ this.createTime = flowRecord.getCreateTime(); this.createOperatorId = flowRecord.getCreateOperatorId(); this.createOperatorName = flowRecord.getCreateOperatorName(); - this.margeKey = flowRecord.getMergeKey(); + this.mergeKey = flowRecord.getMergeKey(); this.mergeable = flowRecord.isMergeable(); this.recordId = flowRecord.getId(); this.timeoutTime = flowRecord.getTimeoutTime(); diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoMargeRepository.java b/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoMargeRepository.java deleted file mode 100644 index 778af68a..00000000 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoMargeRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.codingapi.flow.repository; - -import com.codingapi.flow.record.FlowTodoMarge; - -import java.util.List; - -public interface FlowTodoMargeRepository { - - void saveAll(List relations); - - void remove(FlowTodoMarge relation); - - List findByTodoId(long todoId); - -} diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoMergeRepository.java b/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoMergeRepository.java new file mode 100644 index 00000000..73b0ce5c --- /dev/null +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoMergeRepository.java @@ -0,0 +1,15 @@ +package com.codingapi.flow.repository; + +import com.codingapi.flow.record.FlowTodoMerge; + +import java.util.List; + +public interface FlowTodoMergeRepository { + + void saveAll(List list); + + void remove(FlowTodoMerge todoMerge); + + List findByTodoId(long todoId); + +} diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoRecordRepository.java b/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoRecordRepository.java index e790f500..5379870b 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoRecordRepository.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/repository/FlowTodoRecordRepository.java @@ -8,7 +8,7 @@ public interface FlowTodoRecordRepository { void saveAll(List margeRecords); - FlowTodoRecord getByMageKey(String key); + FlowTodoRecord getByMergeKey(String key); void remove(FlowTodoRecord margeRecord); diff --git a/flow-engine-framework/src/main/java/com/codingapi/flow/service/FlowService.java b/flow-engine-framework/src/main/java/com/codingapi/flow/service/FlowService.java index 8bbcb7bf..79363a7e 100644 --- a/flow-engine-framework/src/main/java/com/codingapi/flow/service/FlowService.java +++ b/flow-engine-framework/src/main/java/com/codingapi/flow/service/FlowService.java @@ -20,7 +20,7 @@ public FlowService(WorkflowRepository workflowRepository, FlowOperatorGateway flowOperatorGateway, FlowRecordRepository flowRecordRepository, FlowTodoRecordRepository flowTodoRecordRepository, - FlowTodoMargeRepository flowTodoMargeRepository, + FlowTodoMergeRepository flowTodoMergeRepository, WorkflowBackupRepository workflowBackupRepository, ParallelBranchRepository parallelBranchRepository, DelayTaskRepository delayTaskRepository, @@ -30,7 +30,7 @@ public FlowService(WorkflowRepository workflowRepository, workflowBackupRepository, flowRecordRepository, flowTodoRecordRepository, - flowTodoMargeRepository, + flowTodoMergeRepository, flowOperatorGateway, parallelBranchRepository, delayTaskRepository, diff --git a/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoMargeRepositoryImpl.java b/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoMergeRepositoryImpl.java similarity index 55% rename from flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoMargeRepositoryImpl.java rename to flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoMergeRepositoryImpl.java index ef8df962..eb1fdaf5 100644 --- a/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoMargeRepositoryImpl.java +++ b/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoMergeRepositoryImpl.java @@ -1,16 +1,16 @@ package com.codingapi.flow.repository; -import com.codingapi.flow.record.FlowTodoMarge; +import com.codingapi.flow.record.FlowTodoMerge; import java.util.HashMap; import java.util.List; import java.util.Map; -public class FlowTodoMargeRepositoryImpl implements FlowTodoMargeRepository { +public class FlowTodoMergeRepositoryImpl implements FlowTodoMergeRepository { - private final Map cache = new HashMap<>(); + private final Map cache = new HashMap<>(); - private void save(FlowTodoMarge relation) { + private void save(FlowTodoMerge relation) { if (relation.getId() > 0) { cache.put(relation.getId(), relation); } else { @@ -21,19 +21,19 @@ private void save(FlowTodoMarge relation) { } @Override - public void remove(FlowTodoMarge relation) { - this.cache.remove(relation.getId()); + public void remove(FlowTodoMerge todoMerge) { + this.cache.remove(todoMerge.getId()); } @Override - public void saveAll(List relations) { - for (FlowTodoMarge relation : relations){ + public void saveAll(List list) { + for (FlowTodoMerge relation : list){ this.save(relation); } } @Override - public List findByTodoId(long todoId) { + public List findByTodoId(long todoId) { return cache.values().stream(). filter(relation -> relation.getTodoId() == todoId) .toList(); diff --git a/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoRecordRepositoryImpl.java b/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoRecordRepositoryImpl.java index 8c95fc08..d877193b 100644 --- a/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoRecordRepositoryImpl.java +++ b/flow-engine-framework/src/test/java/com/codingapi/flow/repository/FlowTodoRecordRepositoryImpl.java @@ -20,7 +20,7 @@ public void save(FlowTodoRecord record) { record.setId(id); cache.put(id, record); } - cacheByMageKey.put(record.getMargeKey(), record); + cacheByMageKey.put(record.getMergeKey(), record); } @Override @@ -32,12 +32,12 @@ public void saveAll(List margeRecords) { @Override public void remove(FlowTodoRecord margeRecord) { - cacheByMageKey.remove(margeRecord.getMargeKey()); + cacheByMageKey.remove(margeRecord.getMergeKey()); cache.remove(margeRecord.getId()); } @Override - public FlowTodoRecord getByMageKey(String key) { + public FlowTodoRecord getByMergeKey(String key) { return cacheByMageKey.get(key); } diff --git a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java index 55089d7c..974562ae 100644 --- a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java +++ b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowMergeableServiceTest.java @@ -18,7 +18,7 @@ import com.codingapi.flow.pojo.request.FlowCreateRequest; import com.codingapi.flow.record.FlowRecord; import com.codingapi.flow.record.FlowTodoRecord; -import com.codingapi.flow.record.FlowTodoMarge; +import com.codingapi.flow.record.FlowTodoMerge; import com.codingapi.flow.repository.*; import com.codingapi.flow.strategy.node.FormFieldPermissionStrategy; import com.codingapi.flow.strategy.node.OperatorLoadStrategy; @@ -38,7 +38,7 @@ public class FlowMergeableServiceTest { private final FlowTodoRecordRepositoryImpl flowTodoMargeRecordRepository = new FlowTodoRecordRepositoryImpl(); - private final FlowTodoMargeRepositoryImpl flowTodoMargeRelationRepository = new FlowTodoMargeRepositoryImpl(); + private final FlowTodoMergeRepositoryImpl flowTodoMargeRelationRepository = new FlowTodoMergeRepositoryImpl(); private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); private final UserGateway userGateway = new UserGateway(); private final WorkflowBackupRepository workflowBackupRepository = new WorkflowBackupRepositoryImpl(); @@ -147,7 +147,7 @@ void mergeableRecords() { assertEquals(1, todoMargeRecords.size()); FlowTodoRecord todoMargeRecord = todoMargeRecords.get(0); - List relationList = flowTodoMargeRelationRepository.findByTodoId(todoMargeRecord.getId()); + List relationList = flowTodoMargeRelationRepository.findByTodoId(todoMargeRecord.getId()); assertEquals(count, relationList.size()); diff --git a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowParallelServiceTest.java b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowParallelServiceTest.java index 810981e7..c0eb723c 100644 --- a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowParallelServiceTest.java +++ b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowParallelServiceTest.java @@ -30,7 +30,7 @@ class FlowParallelServiceTest { private final FlowTodoRecordRepositoryImpl flowTodoMargeRecordRepository = new FlowTodoRecordRepositoryImpl(); - private final FlowTodoMargeRepositoryImpl flowTodoMargeRelationRepository = new FlowTodoMargeRepositoryImpl(); + private final FlowTodoMergeRepositoryImpl flowTodoMargeRelationRepository = new FlowTodoMergeRepositoryImpl(); private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); private final UserGateway userGateway = new UserGateway(); private final WorkflowBackupRepository workflowBackupRepository = new WorkflowBackupRepositoryImpl(); diff --git a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowSampleServiceTest.java b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowSampleServiceTest.java index 57a5e696..59bde7d5 100644 --- a/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowSampleServiceTest.java +++ b/flow-engine-framework/src/test/java/com/codingapi/flow/service/FlowSampleServiceTest.java @@ -38,7 +38,7 @@ class FlowSampleServiceTest { private final FlowTodoRecordRepositoryImpl flowTodoMargeRecordRepository = new FlowTodoRecordRepositoryImpl(); - private final FlowTodoMargeRepositoryImpl flowTodoMargeRelationRepository = new FlowTodoMargeRepositoryImpl(); + private final FlowTodoMergeRepositoryImpl flowTodoMargeRelationRepository = new FlowTodoMergeRepositoryImpl(); private final FlowRecordRepositoryImpl flowRecordRepository = new FlowRecordRepositoryImpl(); private final UserGateway userGateway = new UserGateway(); private final WorkflowBackupRepository workflowBackupRepository = new WorkflowBackupRepositoryImpl(); diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/AutoConfiguration.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/AutoConfiguration.java index 5f0705c0..5c3d5901 100644 --- a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/AutoConfiguration.java +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/AutoConfiguration.java @@ -43,4 +43,14 @@ public FlowRecordRepository flowRecordRepository(FlowRecordEntityRepository flow return new FlowRecordRepositoryImpl(flowRecordEntityRepository); } + @Bean + public FlowTodoRecordRepository flowTodoRecordRepository(FlowTodoRecordEntityRepository flowTodoRecordEntityRepository){ + return new FlowTodoRecordRepositoryImpl(flowTodoRecordEntityRepository); + } + + @Bean + public FlowTodoMergeRepository flowTodoMargeRepository(FlowTodoMargeEntityRepository flowTodoMargeEntityRepository){ + return new FlowTodoMergeRepositoryImpl(flowTodoMargeEntityRepository); + } + } diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/convert/FlowTodoMargeConvertor.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/convert/FlowTodoMargeConvertor.java new file mode 100644 index 00000000..c03dcd32 --- /dev/null +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/convert/FlowTodoMargeConvertor.java @@ -0,0 +1,31 @@ +package com.codingapi.flow.infra.convert; + +import com.codingapi.flow.infra.entity.FlowTodoMargeEntity; +import com.codingapi.flow.record.FlowTodoMerge; + +public class FlowTodoMargeConvertor { + + public static FlowTodoMerge convert(FlowTodoMargeEntity entity) { + if(entity==null){ + return null; + } + return new FlowTodoMerge( + entity.getId(), + entity.getTodoId(), + entity.getRecordId(), + entity.getCreateTime() + ); + } + + public static FlowTodoMargeEntity convert(FlowTodoMerge marge) { + if(marge==null){ + return null; + } + FlowTodoMargeEntity entity = new FlowTodoMargeEntity(); + entity.setId(marge.getId()); + entity.setTodoId(marge.getTodoId()); + entity.setRecordId(marge.getRecordId()); + entity.setCreateTime(marge.getCreateTime()); + return entity; + } +} diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/convert/FlowTodoRecordConvertor.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/convert/FlowTodoRecordConvertor.java new file mode 100644 index 00000000..99aea3fb --- /dev/null +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/convert/FlowTodoRecordConvertor.java @@ -0,0 +1,61 @@ +package com.codingapi.flow.infra.convert; + +import com.codingapi.flow.infra.entity.FlowTodoRecordEntity; +import com.codingapi.flow.record.FlowTodoRecord; + +public class FlowTodoRecordConvertor { + + public static FlowTodoRecord convert(FlowTodoRecordEntity entity){ + if(entity==null){ + return null; + } + return new FlowTodoRecord( + entity.getId(), + entity.getProcessId(), + entity.getWorkBackupId(), + entity.getWorkCode(), + entity.getNodeId(), + entity.getNodeType(), + entity.getTitle(), + entity.getReadTime(), + entity.getCurrentOperatorId(), + entity.getCurrentOperatorName(), + entity.getCreateTime(), + entity.getCreateOperatorId(), + entity.getCreateOperatorName(), + entity.getMergeKey(), + entity.getMargeCount(), + entity.getMergeable(), + entity.getRecordId(), + entity.getTimeoutTime() + ); + } + + + public static FlowTodoRecordEntity convert(FlowTodoRecord record){ + if(record==null){ + return null; + } + + FlowTodoRecordEntity entity = new FlowTodoRecordEntity(); + entity.setId(record.getId()); + entity.setProcessId(record.getProcessId()); + entity.setWorkBackupId(record.getWorkBackupId()); + entity.setWorkCode(record.getWorkCode()); + entity.setNodeId(record.getNodeId()); + entity.setNodeType(record.getNodeType()); + entity.setTitle(record.getTitle()); + entity.setReadTime(record.getReadTime()); + entity.setCurrentOperatorId(record.getCurrentOperatorId()); + entity.setCurrentOperatorName(record.getCurrentOperatorName()); + entity.setCreateTime(record.getCreateTime()); + entity.setCreateOperatorId(record.getCreateOperatorId()); + entity.setCreateOperatorName(record.getCreateOperatorName()); + entity.setMergeKey(record.getMergeKey()); + entity.setMargeCount(record.getMargeCount()); + entity.setMergeable(record.isMergeable()); + entity.setRecordId(record.getRecordId()); + entity.setTimeoutTime(record.getTimeoutTime()); + return entity; + } +} diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/entity/FlowTodoMargeEntity.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/entity/FlowTodoMargeEntity.java new file mode 100644 index 00000000..515cc0ca --- /dev/null +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/entity/FlowTodoMargeEntity.java @@ -0,0 +1,26 @@ +package com.codingapi.flow.infra.entity; + +import jakarta.persistence.*; +import lombok.Data; + +@Data +@Entity +@Table(name = "t_flow_todo_marge") +public class FlowTodoMargeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + /** + * 待办id + */ + private Long todoId; + /** + * 待办记录id + */ + private Long recordId; + /** + * 创建时间 + */ + private Long createTime; +} diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/entity/FlowTodoRecordEntity.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/entity/FlowTodoRecordEntity.java new file mode 100644 index 00000000..e0c50dea --- /dev/null +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/entity/FlowTodoRecordEntity.java @@ -0,0 +1,100 @@ +package com.codingapi.flow.infra.entity; + +import com.codingapi.flow.record.FlowRecord; +import jakarta.persistence.*; +import lombok.Data; + +@Data +@Entity +@Table(name = "t_flow_todo_record") +public class FlowTodoRecordEntity { + + /** + * 合并记录id + */ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + /** + * 流程id + * 每一次流程启动时生成,直到流程结束 + */ + private String processId; + + /** + * 工作id + */ + private Long workBackupId; + /** + * 流程编码 + */ + private String workCode; + /** + * 节点id + */ + private String nodeId; + /** + * 节点类型 + */ + private String nodeType; + + /** + * 消息标题 + */ + private String title; + /** + * 读取时间 + */ + private Long readTime; + + /** + * 当前审批人Id + */ + private Long currentOperatorId; + + /** + * 当前审批人名称 + */ + private String currentOperatorName; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 发起者id + */ + private Long createOperatorId; + /** + * 发起者名称 + */ + private String createOperatorName; + + /** + * 合并记录id,当存在合并记录数据时待办记录数量不会增加,内容会更新至最新的待办数据信息。 + * {@link FlowRecord#getMergeKey()} + */ + private String mergeKey; + + /** + * 合并记录数量 + */ + private Integer margeCount; + + /** + * 是否可合并 + */ + private Boolean mergeable; + + /** + * 待办记录id + */ + private Long recordId; + + /** + * 超时到期时间 + */ + private Long timeoutTime; +} diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowRecordEntityRepository.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowRecordEntityRepository.java index 83bd902e..3f46eb6c 100644 --- a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowRecordEntityRepository.java +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowRecordEntityRepository.java @@ -30,5 +30,8 @@ public interface FlowRecordEntityRepository extends FastRepository findDoneRecordPage(long operatorId, PageRequest pageRequest); + @Query("from FlowRecordEntity r where r.currentOperatorId = ?1 and r.notify = true and r.hidden=false and r.revoked = false ") + Page findNotifyRecordPage(long operatorId, PageRequest pageRequest); + } diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowTodoMargeEntityRepository.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowTodoMargeEntityRepository.java new file mode 100644 index 00000000..342c2eb7 --- /dev/null +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowTodoMargeEntityRepository.java @@ -0,0 +1,11 @@ +package com.codingapi.flow.infra.jpa; + +import com.codingapi.flow.infra.entity.FlowTodoMargeEntity; +import com.codingapi.springboot.fast.jpa.repository.FastRepository; + +import java.util.List; + +public interface FlowTodoMargeEntityRepository extends FastRepository { + + List findByTodoId(long todoId); +} diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowTodoRecordEntityRepository.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowTodoRecordEntityRepository.java new file mode 100644 index 00000000..1f3a618f --- /dev/null +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/jpa/FlowTodoRecordEntityRepository.java @@ -0,0 +1,16 @@ +package com.codingapi.flow.infra.jpa; + +import com.codingapi.flow.infra.entity.FlowTodoRecordEntity; +import com.codingapi.springboot.fast.jpa.repository.FastRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.repository.Query; + +public interface FlowTodoRecordEntityRepository extends FastRepository { + + FlowTodoRecordEntity getByMergeKey(String mergeKey); + + + @Query("from FlowTodoRecordEntity r where r.currentOperatorId = ?1") + Page findTodoRecordPage(long currentOperatorId, PageRequest pageRequest); +} diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/pojo/FlowRecordContent.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/pojo/FlowRecordContent.java new file mode 100644 index 00000000..ae40643e --- /dev/null +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/pojo/FlowRecordContent.java @@ -0,0 +1,156 @@ +package com.codingapi.flow.infra.pojo; + +import com.codingapi.flow.infra.entity.FlowRecordEntity; +import com.codingapi.flow.infra.entity.FlowTodoRecordEntity; +import com.codingapi.flow.record.FlowRecord; +import lombok.Data; + +@Data +public class FlowRecordContent { + + /** + * 流程id + * 每一次流程启动时生成,直到流程结束 + */ + private String processId; + + /** + * 工作id + */ + private Long workBackupId; + /** + * 流程编码 + */ + private String workCode; + /** + * 节点id + */ + private String nodeId; + /** + * 节点类型 + */ + private String nodeType; + + /** + * 消息标题 + */ + private String title; + /** + * 读取时间 + */ + private Long readTime; + + /** + * 当前审批人Id + */ + private Long currentOperatorId; + + /** + * 当前审批人名称 + */ + private String currentOperatorName; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 发起者id + */ + private Long createOperatorId; + /** + * 发起者名称 + */ + private String createOperatorName; + + /** + * 合并记录id,当存在合并记录数据时待办记录数量不会增加,内容会更新至最新的待办数据信息。 + * {@link FlowRecord#getMergeKey()} + */ + private String mergeKey; + + /** + * 合并记录数量 + */ + private Integer margeCount; + + /** + * 是否可合并 + */ + private Boolean mergeable; + + /** + * 待办记录id + */ + private Long recordId; + + /** + * 超时到期时间 + */ + private Long timeoutTime; + + /** + * 节点状态 | 待办、已办 + */ + private Integer recordState; + /** + * 流程状态 | 运行中、已完成、异常、删除 + */ + private Integer flowState; + + /** + * 是否抄送 + */ + private Boolean notify; + + + public static FlowRecordContent convert(FlowTodoRecordEntity todoRecord){ + FlowRecordContent content = new FlowRecordContent(); + content.setProcessId(todoRecord.getProcessId()); + content.setWorkBackupId(todoRecord.getWorkBackupId()); + content.setWorkCode(todoRecord.getWorkCode()); + content.setNodeId(todoRecord.getNodeId()); + content.setNodeType(todoRecord.getNodeType()); + content.setTitle(todoRecord.getTitle()); + content.setReadTime(todoRecord.getReadTime()); + content.setCurrentOperatorId(todoRecord.getCurrentOperatorId()); + content.setCurrentOperatorName(todoRecord.getCurrentOperatorName()); + content.setCreateTime(todoRecord.getCreateTime()); + content.setCreateOperatorId(todoRecord.getCreateOperatorId()); + content.setCreateOperatorName(todoRecord.getCreateOperatorName()); + content.setMergeKey(todoRecord.getMergeKey()); + content.setMargeCount(todoRecord.getMargeCount()); + content.setMergeable(todoRecord.getMergeable()); + content.setRecordId(todoRecord.getRecordId()); + content.setTimeoutTime(todoRecord.getTimeoutTime()); + content.setRecordState(FlowRecord.SATE_RECORD_TODO); + content.setFlowState(FlowRecord.SATE_FLOW_RUNNING); + content.setNotify(false); + return content; + } + + + public static FlowRecordContent convert(FlowRecordEntity record){ + FlowRecordContent content = new FlowRecordContent(); + content.setProcessId(record.getProcessId()); + content.setWorkBackupId(record.getWorkBackupId()); + content.setWorkCode(record.getWorkCode()); + content.setNodeId(record.getNodeId()); + content.setNodeType(record.getNodeType()); + content.setTitle(record.getTitle()); + content.setReadTime(record.getReadTime()); + content.setCurrentOperatorId(record.getCurrentOperatorId()); + content.setCurrentOperatorName(record.getCurrentOperatorName()); + content.setCreateTime(record.getCreateTime()); + content.setCreateOperatorId(record.getCreateOperatorId()); + content.setCreateOperatorName(record.getCreateOperatorName()); + content.setMergeable(record.getMergeable()); + content.setRecordId(record.getId()); + content.setTimeoutTime(record.getTimeoutTime()); + content.setRecordState(record.getRecordState()); + content.setFlowState(record.getFlowState()); + content.setNotify(record.getNotify()); + return content; + } +} diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/repository/impl/FlowTodoMergeRepositoryImpl.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/repository/impl/FlowTodoMergeRepositoryImpl.java new file mode 100644 index 00000000..eb5b1ce4 --- /dev/null +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/repository/impl/FlowTodoMergeRepositoryImpl.java @@ -0,0 +1,40 @@ +package com.codingapi.flow.infra.repository.impl; + +import com.codingapi.flow.infra.convert.FlowTodoMargeConvertor; +import com.codingapi.flow.infra.entity.FlowTodoMargeEntity; +import com.codingapi.flow.infra.jpa.FlowTodoMargeEntityRepository; +import com.codingapi.flow.record.FlowTodoMerge; +import com.codingapi.flow.repository.FlowTodoMergeRepository; +import lombok.AllArgsConstructor; + +import java.util.List; + +@AllArgsConstructor +public class FlowTodoMergeRepositoryImpl implements FlowTodoMergeRepository { + + private final FlowTodoMargeEntityRepository flowTodoMargeEntityRepository; + + @Override + public void saveAll(List list) { + for (FlowTodoMerge relation : list){ + this.save(relation); + } + } + + private void save(FlowTodoMerge todoMarge){ + FlowTodoMargeEntity entity = FlowTodoMargeConvertor.convert(todoMarge); + flowTodoMargeEntityRepository.save(entity); + todoMarge.setId(entity.getId()); + } + + @Override + public void remove(FlowTodoMerge todoMerge) { + flowTodoMargeEntityRepository.deleteById(todoMerge.getId()); + } + + @Override + public List findByTodoId(long todoId) { + return flowTodoMargeEntityRepository.findByTodoId(todoId) + .stream().map(FlowTodoMargeConvertor::convert).toList(); + } +} diff --git a/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/repository/impl/FlowTodoRecordRepositoryImpl.java b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/repository/impl/FlowTodoRecordRepositoryImpl.java new file mode 100644 index 00000000..3d1db26b --- /dev/null +++ b/flow-engine-starter-infra/src/main/java/com/codingapi/flow/infra/repository/impl/FlowTodoRecordRepositoryImpl.java @@ -0,0 +1,40 @@ +package com.codingapi.flow.infra.repository.impl; + +import com.codingapi.flow.infra.convert.FlowTodoRecordConvertor; +import com.codingapi.flow.infra.entity.FlowTodoRecordEntity; +import com.codingapi.flow.infra.jpa.FlowTodoRecordEntityRepository; +import com.codingapi.flow.record.FlowTodoRecord; +import com.codingapi.flow.repository.FlowTodoRecordRepository; +import lombok.AllArgsConstructor; + +import java.util.List; + +@AllArgsConstructor +public class FlowTodoRecordRepositoryImpl implements FlowTodoRecordRepository { + + private final FlowTodoRecordEntityRepository flowTodoRecordEntityRepository; + + @Override + public void saveAll(List margeRecords) { + for (FlowTodoRecord record : margeRecords){ + this.save(record); + } + } + + @Override + public FlowTodoRecord getByMergeKey(String key) { + return FlowTodoRecordConvertor.convert(flowTodoRecordEntityRepository.getByMergeKey(key)); + } + + @Override + public void remove(FlowTodoRecord margeRecord) { + flowTodoRecordEntityRepository.deleteById(margeRecord.getId()); + } + + @Override + public void save(FlowTodoRecord margeRecord) { + FlowTodoRecordEntity entity = FlowTodoRecordConvertor.convert(margeRecord); + flowTodoRecordEntityRepository.save(entity); + margeRecord.setId(entity.getId()); + } +} diff --git a/flow-engine-starter-query/src/main/java/com/codingapi/flow/query/controller/FlowRecordQueryController.java b/flow-engine-starter-query/src/main/java/com/codingapi/flow/query/controller/FlowRecordQueryController.java index 1d896d07..976fd4ce 100644 --- a/flow-engine-starter-query/src/main/java/com/codingapi/flow/query/controller/FlowRecordQueryController.java +++ b/flow-engine-starter-query/src/main/java/com/codingapi/flow/query/controller/FlowRecordQueryController.java @@ -1,12 +1,16 @@ package com.codingapi.flow.query.controller; import com.codingapi.flow.infra.entity.FlowRecordEntity; +import com.codingapi.flow.infra.entity.FlowTodoRecordEntity; import com.codingapi.flow.infra.jpa.FlowRecordEntityRepository; +import com.codingapi.flow.infra.jpa.FlowTodoRecordEntityRepository; +import com.codingapi.flow.infra.pojo.FlowRecordContent; import com.codingapi.flow.operator.IFlowOperator; import com.codingapi.springboot.framework.dto.request.SearchRequest; import com.codingapi.springboot.framework.dto.response.MultiResponse; import com.codingapi.springboot.framework.user.UserContext; import lombok.AllArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -18,13 +22,15 @@ public class FlowRecordQueryController { private final FlowRecordEntityRepository flowRecordEntityRepository; + private final FlowTodoRecordEntityRepository flowTodoRecordEntityRepository; /** * 全部流程记录接口 */ @GetMapping("/list") - public MultiResponse list(SearchRequest request) { - return MultiResponse.of(flowRecordEntityRepository.searchRequest(request)); + public MultiResponse list(SearchRequest request) { + Page page = flowRecordEntityRepository.searchRequest(request); + return MultiResponse.of(page.map(FlowRecordContent::convert)); } @@ -32,10 +38,22 @@ public MultiResponse list(SearchRequest request) { * 我的待办记录 */ @GetMapping("/todo") - public MultiResponse todo(SearchRequest request) { + public MultiResponse todo(SearchRequest request) { IFlowOperator current = (IFlowOperator) UserContext.getInstance().current(); PageRequest pageRequest = request.toPageRequest(FlowRecordEntity.class); - return MultiResponse.of(flowRecordEntityRepository.findTodoRecordPage(current.getUserId(),pageRequest)); + Page page = flowTodoRecordEntityRepository.findTodoRecordPage(current.getUserId(),pageRequest); + return MultiResponse.of(page.map(FlowRecordContent::convert)); + } + + /** + * 我的抄送记录 + */ + @GetMapping("/notify") + public MultiResponse notify(SearchRequest request) { + IFlowOperator current = (IFlowOperator) UserContext.getInstance().current(); + PageRequest pageRequest = request.toPageRequest(FlowRecordEntity.class); + Page page =flowRecordEntityRepository.findNotifyRecordPage(current.getUserId(),pageRequest); + return MultiResponse.of(page.map(FlowRecordContent::convert)); } @@ -43,9 +61,10 @@ public MultiResponse todo(SearchRequest request) { * 我的已办记录 */ @GetMapping("/done") - public MultiResponse done(SearchRequest request) { + public MultiResponse done(SearchRequest request) { IFlowOperator current = (IFlowOperator) UserContext.getInstance().current(); PageRequest pageRequest = request.toPageRequest(FlowRecordEntity.class); - return MultiResponse.of(flowRecordEntityRepository.findDoneRecordPage(current.getUserId(),pageRequest)); + Page page =flowRecordEntityRepository.findDoneRecordPage(current.getUserId(),pageRequest); + return MultiResponse.of(page.map(FlowRecordContent::convert)); } } diff --git a/flow-engine-starter/src/main/java/com/codingapi/flow/AutoConfiguration.java b/flow-engine-starter/src/main/java/com/codingapi/flow/AutoConfiguration.java index cdd4ba7e..9ee3f17a 100644 --- a/flow-engine-starter/src/main/java/com/codingapi/flow/AutoConfiguration.java +++ b/flow-engine-starter/src/main/java/com/codingapi/flow/AutoConfiguration.java @@ -38,6 +38,8 @@ public RepositoryHolderContextRegister repositoryHolderContextRegister( WorkflowRepository workflowRepository, WorkflowBackupRepository workflowBackupRepository, FlowRecordRepository flowRecordRepository, + FlowTodoRecordRepository flowTodoRecordRepository, + FlowTodoMergeRepository flowTodoMergeRepository, FlowOperatorGateway flowOperatorGateway, ParallelBranchRepository parallelBranchRepository, DelayTaskRepository delayTaskRepository, @@ -47,6 +49,8 @@ public RepositoryHolderContextRegister repositoryHolderContextRegister( workflowRepository, workflowBackupRepository, flowRecordRepository, + flowTodoRecordRepository, + flowTodoMergeRepository, flowOperatorGateway, parallelBranchRepository, delayTaskRepository, @@ -59,6 +63,8 @@ public FlowService flowService( WorkflowRepository workflowRepository, FlowOperatorGateway flowOperatorGateway, FlowRecordRepository flowRecordRepository, + FlowTodoRecordRepository flowTodoRecordRepository, + FlowTodoMergeRepository flowTodoMergeRepository, WorkflowBackupRepository workflowBackupRepository, ParallelBranchRepository parallelBranchRepository, DelayTaskRepository delayTaskRepository, @@ -68,6 +74,8 @@ public FlowService flowService( workflowRepository, flowOperatorGateway, flowRecordRepository, + flowTodoRecordRepository, + flowTodoMergeRepository, workflowBackupRepository, parallelBranchRepository, delayTaskRepository, diff --git a/flow-engine-starter/src/main/java/com/codingapi/flow/register/RepositoryHolderContextRegister.java b/flow-engine-starter/src/main/java/com/codingapi/flow/register/RepositoryHolderContextRegister.java index 0b8409cf..fa9936ba 100644 --- a/flow-engine-starter/src/main/java/com/codingapi/flow/register/RepositoryHolderContextRegister.java +++ b/flow-engine-starter/src/main/java/com/codingapi/flow/register/RepositoryHolderContextRegister.java @@ -12,6 +12,8 @@ public class RepositoryHolderContextRegister implements InitializingBean { private final WorkflowRepository workflowRepository; private final WorkflowBackupRepository workflowBackupRepository; private final FlowRecordRepository flowRecordRepository; + private final FlowTodoRecordRepository flowTodoRecordRepository; + private final FlowTodoMergeRepository flowTodoMergeRepository; private final FlowOperatorGateway flowOperatorGateway; private final ParallelBranchRepository parallelBranchRepository; private final DelayTaskRepository delayTaskRepository; @@ -24,6 +26,8 @@ public void afterPropertiesSet() throws Exception { workflowRepository, workflowBackupRepository, flowRecordRepository, + flowTodoRecordRepository, + flowTodoMergeRepository, flowOperatorGateway, parallelBranchRepository, delayTaskRepository,