# 工作流使用指南 ## Flowable 工作流引擎 ### 核心概念 - **流程定义 (Process Definition)**: 流程的静态描述 - **流程实例 (Process Instance)**: 流程的运行实例 - **任务 (Task)**: 需要人工处理的节点 - **执行实例 (Execution)**: 流程执行的路径 ### 数据库表结构 ```sql -- 流程定义相关 ACT_RE_DEPLOYMENT -- 部署信息 ACT_RE_PROCDEF -- 流程定义 -- 运行时数据 ACT_RU_EXECUTION -- 执行实例 ACT_RU_TASK -- 运行时任务 ACT_RU_VARIABLE -- 运行时变量 -- 历史数据 ACT_HI_PROCINST -- 历史流程实例 ACT_HI_TASKINST -- 历史任务实例 ACT_HI_ACTINST -- 历史活动实例 ``` ## 流程设计器 ### BPMN 设计器 支持标准 BPMN 2.0 规范,适合复杂流程设计: ```xml ${deptLeader} ${hrManager} ``` ### Simple 设计器 (仿钉钉) 支持拖拽式流程设计,适合简单审批流程: ```json { "name": "请假流程", "version": 1, "nodes": [ { "id": "start", "type": "START", "name": "发起人" }, { "id": "approval1", "type": "APPROVAL", "name": "部门主管审批", "assigneeType": "ROLE", "assignees": ["dept_manager"] }, { "id": "approval2", "type": "APPROVAL", "name": "HR审批", "assigneeType": "USER", "assignees": ["hr001"] }, { "id": "end", "type": "END", "name": "结束" } ] } ``` ## 流程部署 ### 程序化部署 ```java @Service public class BpmDeploymentService { @Resource private RepositoryService repositoryService; /** * 部署 BPMN 流程 */ public String deployBpmnProcess(String processName, InputStream bpmnStream) { Deployment deployment = repositoryService.createDeployment() .name(processName) .addInputStream(processName + ".bpmn20.xml", bpmnStream) .deploy(); return deployment.getId(); } /** * 删除流程部署 */ public void deleteDeployment(String deploymentId) { repositoryService.deleteDeployment(deploymentId, true); } /** * 获取流程定义列表 */ public List getProcessDefinitions() { return repositoryService.createProcessDefinitionQuery() .latestVersion() .list(); } } ``` ### 流程版本管理 ```java @Service public class ProcessVersionService { /** * 升级流程版本 */ public void upgradeProcessVersion(String processKey, InputStream newBpmn) { // 部署新版本 String deploymentId = deployBpmnProcess(processKey + "_v2", newBpmn); // 迁移运行中的实例(可选) migrateRunningInstances(processKey); } /** * 迁移运行中的流程实例 */ private void migrateRunningInstances(String processKey) { // 获取旧版本的流程实例 List instances = runtimeService .createProcessInstanceQuery() .processDefinitionKey(processKey) .list(); // 执行实例迁移逻辑 for (ProcessInstance instance : instances) { // 具体的迁移策略 } } } ``` ## 流程启动 ### 启动流程实例 ```java @Service public class BpmProcessService { @Resource private RuntimeService runtimeService; /** * 启动流程 */ public String startProcess(String processKey, String businessKey, Map variables, Long startUserId) { // 设置启动用户 identityService.setAuthenticatedUserId(String.valueOf(startUserId)); // 启动流程实例 ProcessInstance processInstance = runtimeService .startProcessInstanceByKey(processKey, businessKey, variables); return processInstance.getProcessInstanceId(); } /** * 启动流程(带表单数据) */ public String startProcessWithForm(String processKey, String businessKey, Map formData, Long startUserId) { Map variables = new HashMap<>(); variables.put("formData", formData); variables.put("startUserId", startUserId); variables.put("startTime", new Date()); return startProcess(processKey, businessKey, variables, startUserId); } } ``` ### 流程变量管理 ```java @Service public class ProcessVariableService { /** * 设置流程变量 */ public void setVariable(String processInstanceId, String variableName, Object value) { runtimeService.setVariable(processInstanceId, variableName, value); } /** * 获取流程变量 */ public Object getVariable(String processInstanceId, String variableName) { return runtimeService.getVariable(processInstanceId, variableName); } /** * 设置局部变量(任务级别) */ public void setTaskLocalVariable(String taskId, String variableName, Object value) { taskService.setVariableLocal(taskId, variableName, value); } } ``` ## 任务处理 ### 任务查询 ```java @Service public class BpmTaskService { @Resource private TaskService taskService; /** * 查询用户待办任务 */ public List getTodoTasks(Long userId) { return taskService.createTaskQuery() .taskAssignee(String.valueOf(userId)) .active() .orderByTaskCreateTime() .desc() .list(); } /** * 查询用户参与的任务(候选用户) */ public List getCandidateTasks(Long userId) { return taskService.createTaskQuery() .taskCandidateUser(String.valueOf(userId)) .active() .orderByTaskCreateTime() .desc() .list(); } /** * 查询角色任务 */ public List getRoleTasks(String roleKey) { return taskService.createTaskQuery() .taskCandidateGroup(roleKey) .active() .orderByTaskCreateTime() .desc() .list(); } } ``` ### 任务处理操作 ```java @Service public class TaskOperationService { /** * 完成任务 */ public void completeTask(String taskId, Map variables, Long userId) { // 设置处理人 identityService.setAuthenticatedUserId(String.valueOf(userId)); // 完成任务 taskService.complete(taskId, variables); // 记录操作日志 recordTaskOperation(taskId, "complete", userId); } /** * 拒绝任务 */ public void rejectTask(String taskId, String reason, Long userId) { Map variables = new HashMap<>(); variables.put("approved", false); variables.put("rejectReason", reason); completeTask(taskId, variables, userId); } /** * 转办任务 */ public void delegateTask(String taskId, Long targetUserId, Long currentUserId) { // 设置任务委派 taskService.delegateTask(taskId, String.valueOf(targetUserId)); // 记录操作 recordTaskOperation(taskId, "delegate", currentUserId); } /** * 认领任务 */ public void claimTask(String taskId, Long userId) { taskService.claim(taskId, String.valueOf(userId)); recordTaskOperation(taskId, "claim", userId); } } ``` ## 流程控制 ### 会签处理 ```java @Service public class MultiInstanceService { /** * 并行会签配置 */ public void configParallelMultiInstance(BpmnModelInstance modelInstance, String taskId, String collection) { UserTask userTask = modelInstance.getModelElementById(taskId); // 设置多实例配置 MultiInstanceLoopCharacteristics multiInstance = modelInstance.newInstance(MultiInstanceLoopCharacteristics.class); multiInstance.setSequential(false); // 并行执行 multiInstance.setCollection(collection); multiInstance.setElementVariable("assignee"); userTask.setLoopCharacteristics(multiInstance); } /** * 串行会签配置 */ public void configSequentialMultiInstance(BpmnModelInstance modelInstance, String taskId, String collection) { UserTask userTask = modelInstance.getModelElementById(taskId); MultiInstanceLoopCharacteristics multiInstance = modelInstance.newInstance(MultiInstanceLoopCharacteristics.class); multiInstance.setSequential(true); // 串行执行 multiInstance.setCollection(collection); multiInstance.setElementVariable("assignee"); userTask.setLoopCharacteristics(multiInstance); } } ``` ### 动态任务分配 ```java @Component public class TaskAssignmentService { /** * 根据部门分配任务 */ public String assignByDept(DelegateTask delegateTask) { // 获取发起人部门 String startUserId = delegateTask.getVariable("startUserId").toString(); UserDO startUser = userService.getUser(Long.valueOf(startUserId)); // 查找部门主管 UserDO deptManager = userService.getDeptManager(startUser.getDeptId()); return String.valueOf(deptManager.getId()); } /** * 根据金额分配任务 */ public String assignByAmount(DelegateTask delegateTask) { BigDecimal amount = (BigDecimal) delegateTask.getVariable("amount"); if (amount.compareTo(new BigDecimal("10000")) > 0) { // 大于1万,总经理审批 return "general_manager"; } else if (amount.compareTo(new BigDecimal("5000")) > 0) { // 大于5千,部门经理审批 return "dept_manager"; } else { // 直接主管审批 return "direct_supervisor"; } } } ``` ## 流程监控 ### 流程实例监控 ```java @Service public class ProcessMonitorService { /** * 获取流程实例状态 */ public ProcessInstanceInfo getProcessInstanceInfo(String processInstanceId) { // 获取流程实例 ProcessInstance processInstance = runtimeService .createProcessInstanceQuery() .processInstanceId(processInstanceId) .singleResult(); if (processInstance != null) { // 运行中 return buildRunningInstanceInfo(processInstance); } else { // 已结束,查询历史 HistoricProcessInstance historicInstance = historyService .createHistoricProcessInstanceQuery() .processInstanceId(processInstanceId) .singleResult(); return buildFinishedInstanceInfo(historicInstance); } } /** * 获取当前活动任务 */ public List getCurrentTasks(String processInstanceId) { return taskService.createTaskQuery() .processInstanceId(processInstanceId) .active() .list(); } /** * 获取流程轨迹 */ public List getProcessTrace(String processInstanceId) { return historyService.createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId) .orderByHistoricActivityInstanceStartTime() .asc() .list(); } } ``` ### 流程统计分析 ```java @Service public class ProcessAnalyticsService { /** * 统计流程执行时长 */ public ProcessDurationStats getProcessDurationStats(String processKey) { // 查询已完成的流程实例 List instances = historyService .createHistoricProcessInstanceQuery() .processDefinitionKey(processKey) .finished() .list(); // 计算统计数据 return calculateDurationStats(instances); } /** * 统计任务处理效率 */ public TaskEfficiencyStats getTaskEfficiencyStats(String taskDefinitionKey) { List tasks = historyService .createHistoricTaskInstanceQuery() .taskDefinitionKey(taskDefinitionKey) .finished() .list(); return calculateTaskEfficiency(tasks); } /** * 获取流程热力图数据 */ public Map getProcessHeatmapData(String processKey) { // 统计各个节点的通过次数 Map heatmap = new HashMap<>(); List activities = historyService .createHistoricActivityInstanceQuery() .processDefinitionKey(processKey) .list(); for (HistoricActivityInstance activity : activities) { String activityId = activity.getActivityId(); heatmap.put(activityId, heatmap.getOrDefault(activityId, 0) + 1); } return heatmap; } } ``` ## 表单集成 ### 动态表单配置 ```java @Service public class FormConfigService { /** * 获取任务表单配置 */ public FormConfigVO getTaskFormConfig(String taskId) { Task task = taskService.createTaskQuery() .taskId(taskId) .singleResult(); // 获取表单配置 String formKey = task.getFormKey(); return formConfigMapper.selectByFormKey(formKey); } /** * 渲染表单字段 */ public List renderFormFields(String taskId) { FormConfigVO formConfig = getTaskFormConfig(taskId); List fields = JSON.parseArray(formConfig.getFieldsConfig(), FormFieldVO.class); // 设置字段权限(可读、可写、隐藏) setFieldPermissions(fields, taskId); return fields; } /** * 设置字段权限 */ private void setFieldPermissions(List fields, String taskId) { Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); String taskDefinitionKey = task.getTaskDefinitionKey(); // 根据任务节点设置字段权限 for (FormFieldVO field : fields) { TaskFieldPermissionDO permission = taskFieldPermissionMapper .selectByTaskAndField(taskDefinitionKey, field.getFieldKey()); if (permission != null) { field.setPermission(permission.getPermission()); } } } } ``` ### 表单数据处理 ```java @Service public class FormDataService { /** * 保存表单数据 */ public void saveFormData(String taskId, Map formData) { // 验证表单数据 validateFormData(taskId, formData); // 保存到流程变量 for (Map.Entry entry : formData.entrySet()) { taskService.setVariable(taskId, entry.getKey(), entry.getValue()); } // 保存到业务表 saveToBusinessTable(taskId, formData); } /** * 获取表单数据 */ public Map getFormData(String taskId) { Map formData = new HashMap<>(); // 从流程变量获取 Map variables = taskService.getVariables(taskId); formData.putAll(variables); // 从业务表获取 Map businessData = getFromBusinessTable(taskId); formData.putAll(businessData); return formData; } } ``` ## 流程扩展 ### 自定义监听器 ```java @Component public class CustomTaskListener implements TaskListener { @Override public void notify(DelegateTask delegateTask) { String eventName = delegateTask.getEventName(); switch (eventName) { case EVENTNAME_CREATE: handleTaskCreate(delegateTask); break; case EVENTNAME_ASSIGNMENT: handleTaskAssignment(delegateTask); break; case EVENTNAME_COMPLETE: handleTaskComplete(delegateTask); break; default: break; } } private void handleTaskCreate(DelegateTask delegateTask) { // 任务创建时的处理逻辑 // 例如:发送通知、记录日志等 sendTaskNotification(delegateTask); } private void handleTaskAssignment(DelegateTask delegateTask) { // 任务分配时的处理逻辑 recordTaskAssignment(delegateTask); } private void handleTaskComplete(DelegateTask delegateTask) { // 任务完成时的处理逻辑 updateBusinessStatus(delegateTask); } } ``` ### 自定义服务任务 ```java @Component("customServiceTask") public class CustomServiceTask implements JavaDelegate { @Override public void execute(DelegateExecution execution) { // 获取流程变量 String businessKey = execution.getProcessBusinessKey(); Map variables = execution.getVariables(); // 执行业务逻辑 Object result = executeBusinessLogic(businessKey, variables); // 设置返回变量 execution.setVariable("serviceResult", result); } private Object executeBusinessLogic(String businessKey, Map variables) { // 具体的业务处理逻辑 // 例如:调用外部服务、更新数据库等 return "处理完成"; } } ``` ## 最佳实践 ### 流程设计原则 1. **简化流程**: 避免过于复杂的流程设计 2. **明确责任**: 每个节点都要有明确的责任人 3. **异常处理**: 考虑各种异常情况的处理 4. **性能优化**: 避免长时间运行的流程 5. **版本管理**: 合理管理流程版本升级 ### 性能优化建议 1. **分页查询**: 大量任务数据使用分页 2. **索引优化**: 为常用查询字段添加索引 3. **历史数据清理**: 定期清理历史流程数据 4. **缓存策略**: 缓存流程定义和用户信息 5. **异步处理**: 耗时操作使用异步任务 ### 监控告警 1. **流程超时**: 监控长时间未处理的任务 2. **错误率**: 监控流程执行错误率 3. **性能指标**: 监控流程执行时长 4. **资源使用**: 监控数据库和内存使用情况