后端集成与代码对接
1. 业务实体与流程定义关联
在新闻发布模块的业务实体(如 News表)中,需增加流程实例关联字段。
java
// News.java 实体类
public class News {
private Long id;
private String title;
private String content;
// ... 其他业务字段 // 流程实例ID,用于关联Warm-Flow流程实例
private String processInstanceId;
// 流程定义Key,固定为新闻审批流程的Key,如:news_approval private String processDefinitionKey;
// 业务状态,用于与流程节点状态同步 private String status;
// 是否加急
private Boolean urgent;
// getters and setters ...
}
2. 流程定义建模与部署
在Warm-Flow设计器中,设计一个支持三级审批和加急路径的流程。关键节点设计如下表所示:
| 节点ID | 节点名称 | 节点类型 | 办理人策略/条件 | 说明 |
|---|---|---|---|---|
| start | 开始 | 开始事件 | - | 流程起点 |
| submit | 提交申请 | 用户任务 | 申请人 | 新闻提交 |
| urgent_gateway | 加急判断 | 排他网关 | ${news.urgent == true} |
判断是否走加急通道 |
| level1_approval | 一级审批 | 用户任务 | 部门经理 | 普通路径第一级审批 |
| level2_approval | 二级审批 | 用户任务 | 中心总监 | 普通路径第二级审批 |
| level3_approval | 三级审批 | 用户任务 | 分管领导 | 普通路径第三级审批 |
| urgent_approval | 加急审批 | 用户任务 | 指定加急审批人 | 加急路径审批节点 |
| end | 结束 | 结束事件 | - | 流程结束 |
将设计好的BPMN流程图(如 news_approval.bpmn)部署到Warm-Flow引擎中,获取流程定义Key(如 news_approval)。
3. 核心服务层实现
创建 NewsWorkflowService 来处理流程相关的业务逻辑。
java
// NewsWorkflowService.java
@Service
public class NewsWorkflowService {
@Autowired
private RuntimeService runtimeService; // Warm-Flow运行时服务
@Autowired
private TaskService taskService; // Warm-Flow任务服务
@Autowired
private INewsService newsService; // 你的新闻业务服务 /**
* 启动新闻审批流程 * @param newsId 新闻ID
* @param variables 流程变量(可包含加急标志、申请人等)
* @return 流程实例ID */
public String startApprovalProcess(Long newsId, Map<String, Object> variables) {
News news = newsService.getById(newsId);
if (news == null) {
throw new RuntimeException("新闻不存在");
}
// 设置业务变量,流程条件判断会用到 variables.put("news", news);
variables.put("urgent", news.getUrgent());
variables.put("applicantUserId", SecurityUtils.getUserId()); // 从若依安全工具获取当前用户
// 启动流程实例 ProcessInstance instance = runtimeService.startProcessInstanceByKey("news_approval", String.valueOf(newsId), variables);
String processInstanceId = instance.getId();
// 更新业务实体,关联流程实例ID
news.setProcessInstanceId(processInstanceId);
news.setProcessDefinitionKey("news_approval");
news.setStatus("审批中");
newsService.updateById(news);
return processInstanceId;
}
/**
* 完成审批任务
* @param taskId 任务ID
* @param approvalResult 审批结果(通过/驳回)
* @param comment 审批意见
*/
public void completeTask(String taskId, String approvalResult, String comment) {
// 获取当前任务
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
throw new RuntimeException("任务不存在或已完成");
}
// 设置流程变量,传递审批结果
Map<String, Object> variables = new HashMap<>();
variables.put("approvalResult", approvalResult);
variables.put("comment", comment);
// 完成任务,引擎会自动流转到下一个节点
taskService.complete(taskId, variables);
// 可以根据任务定义Key(task.getTaskDefinitionKey())来更新业务状态
updateBusinessStatus(task.getProcessInstanceId(), task.getTaskDefinitionKey(), approvalResult);
}
/**
* 查询用户的待办任务
* @param userId 用户ID * @return 任务列表
*/
public List<Task> getTodoTasks(String userId) {
return taskService.createTaskQuery()
.taskAssignee(userId)
.orderByTaskCreateTime().desc()
.list();
}
/**
* 根据流程实例和任务节点更新业务状态(示例)
*/
private void updateBusinessStatus(String processInstanceId, String taskKey, String result) {
// 根据processInstanceId反查业务数据(这里假设processInstance的businessKey是newsId)
ProcessInstance instance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
Long newsId = Long.valueOf(instance.getBusinessKey());
News news = newsService.getById(newsId);
String newStatus = "审批中";
// 根据实际节点和结果更新状态 if ("level3_approval".equals(taskKey) && "通过".equals(result)) {
newStatus = "审批通过";
} else if ("驳回".equals(result)) {
newStatus = "已驳回";
}
// ... 其他状态逻辑 news.setStatus(newStatus);
newsService.updateById(news);
}
}
4. 办理人策略实现(关键)
三级审批和加急审批涉及不同的人员指派。需要实现Warm-Flow的 TaskAssigneeStrategy 接口或使用其内置的 FlwTaskAssigneeServiceImpl 进行扩展。
java
// CustomTaskAssigneeService.java 实现动态任务分配
@Component
public class CustomTaskAssigneeService implements TaskAssigneeService {
@Autowired private ISysUserService userService; // 若依用户服务
@Autowired
private ISysDeptService deptService; // 若依部门服务
@Override
public String getAssignee(String processDefinitionId, String taskDefinitionKey, Map<String, Object> variables) {
// 1. 获取流程变量中的业务数据 News news = (News) variables.get("news");
Boolean isUrgent = (Boolean) variables.get("urgent");
// 2. 根据任务节点Key和业务逻辑分配办理人
String assigneeUserId = null;
switch (taskDefinitionKey) {
case "submit":
// 提交任务,指派给申请人自己(在启动时已设置)
assigneeUserId = (String) variables.get("applicantUserId");
break;
case "level1_approval":
// 一级审批:申请人的部门经理
Long deptId = news.getCreateDeptId(); // 假设新闻实体有创建部门ID SysUser deptManager = userService.selectUserByPostCodeAndDeptId("dept_manager", deptId); // 自定义方法,根据岗位编码和部门查找 assigneeUserId = deptManager != null ? String.valueOf(deptManager.getUserId()) : null;
break;
case "level2_approval":
// 二级审批:中心总监(可能是跨部门的角色)
assigneeUserId = resolveDirectorAssignee(news);
break;
case "level3_approval":
// 三级审批:分管领导(根据新闻类型或部门决定)
assigneeUserId = resolveLeaderAssignee(news);
break;
case "urgent_approval":
// 加急审批:指定特定的加急审批人ID,可从配置或变量中读取
assigneeUserId = (String) variables.get("urgentApproverId");
if (assigneeUserId == null) {
// 默认加急审批人,例如系统管理员
assigneeUserId = "1";
}
break;
default:
// 默认指派给流程发起人 assigneeUserId = (String) variables.get("applicantUserId");
}
return assigneeUserId;
}
private String resolveDirectorAssignee(News news) {
// 实现你的逻辑,例如根据新闻所属栏目找到对应的中心总监角色用户 // 这里返回一个示例用户ID return "3";
}
private String resolveLeaderAssignee(News news) {
// 实现你的逻辑
return "4";
}
}
配置Warm-Flow使用此策略 :在 application.yml 中指定自定义的办理人服务Bean名称。
yaml
warm-flow:
task-assignee-service: customTaskAssigneeService # 对应上面@Component的bean name
5. 流程监听器(可选但推荐)
使用执行监听器或任务监听器,在流程关键节点(如流程启动、任务完成、流程结束)自动同步业务状态,实现业务与流程解耦。
java
// NewsProcessEventListener.java
@Component
public class NewsProcessEventListener {
@Autowired
private INewsService newsService;
// 监听流程结束事件
@EventListener(condition = "#event.eventType=='PROCESS_COMPLETED'")
public void onProcessCompleted(FlowableEvent event) {
FlowableProcessCompletedEvent completedEvent = (FlowableProcessCompletedEvent) event;
String processInstanceId = completedEvent.getProcessInstanceId();
// 根据流程实例ID找到业务数据并更新最终状态
// ... 查询逻辑
// news.setStatus("流程结束");
// newsService.updateById(news);
}
}
前端集成与代码对接
1. 集成流程设计器(管理端)
Ruoyi-Vue-Plus已集成 warm-flow-plugin-ui-sb-web前端组件。你可以在系统管理菜单下找到流程设计器入口,用于绘制和部署包含三级审批与加急网关的BPMN流程图。
2. 新闻模块前端页面改造
在新闻发布/管理页面中,增加流程操作按钮和状态展示。
vue
<!-- NewsList.vue 列表页片段 -->
<template>
<div class="app-container">
<el-table :data="newsList">
<el-table-column prop="title" label="标题"/>
<el-table-column prop="status" label="审批状态">
<template #default="scope">
<el-tag :type="statusTagType(scope.row.status)">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="scope">
<!-- 只有草稿状态的新闻可以提交审批 -->
<el-button v-if="scope.row.status === '草稿'" size="small" @click="handleSubmitApproval(scope.row)">
提交审批 </el-button>
<!-- 查看审批进度 -->
<el-button size="small" @click="handleViewProgress(scope.row)">
审批进度
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup>
import { submitApproval } from '@/api/workflow/news'; // 新增的流程API
// 提交审批
const handleSubmitApproval = async (row) => {
// 弹出对话框,确认是否加急
const { urgent } = await ElMessageBox.confirm('是否加急审批?', '提示', {
confirmButtonText: '加急',
cancelButtonText: '普通',
type: 'warning',
distinguishCancelAndClose: true,
}).then(() => ({ urgent: true })).catch(action => ({
urgent: action === 'cancel' ? false : undefined }));
if (urgent === undefined) return; // 点击了关闭 // 调用后端启动流程接口 const params = { newsId: row.id, urgent };
const { data } = await submitApproval(params);
ElMessage.success('已提交审批,流程实例ID:' + data);
// 刷新列表
getList();
};
</script>
3. 待办任务与审批页面
利用Warm-Flow提供的前端组件或API,开发一个统一的待办任务页面,或将其集成到新闻详情页进行审批。
vue
<!-- TodoTask.vue 或 NewsDetail.vue 审批部分 -->
<template>
<div v-if="currentTask">
<el-card header="审批任务">
<div>任务名称:{{ currentTask.name }}</div>
<div>创建时间:{{ parseTime(currentTask.createTime) }}</div>
<el-form :model="approvalForm" label-width="80px">
<el-form-item label="审批意见">
<el-input v-model="approvalForm.comment" type="textarea"/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleApprove('通过')">同意</el-button>
<el-button type="danger" @click="handleApprove('驳回')">驳回</el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 可以集成Warm-Flow的流程图高亮组件,显示当前节点 -->
<!-- <flow-viewer :process-instance-id="processInstanceId"/> -->
</div>
</template>
<script setup>
import { getCurrentTask, completeTask } from '@/api/workflow/task'; // 调用流程任务API
// 完成任务
const handleApprove = async (result) => {
const params = {
taskId: currentTask.value.id,
approvalResult: result,
comment: approvalForm.value.comment };
await completeTask(params);
ElMessage.success('审批操作完成');
// 刷新任务或跳转
};
</script>
4. API接口定义
前端需要调用的后端API示例:
java
// WorkflowNewsController.java
@RestController
@RequestMapping("/workflow/news")
public class WorkflowNewsController {
@Autowired private NewsWorkflowService newsWorkflowService;
/**
* 提交新闻审批 */
@PostMapping("/submit")
public AjaxResult submit(@RequestBody NewsApprovalReq req) {
Map<String, Object> variables = new HashMap<>();
variables.put("urgent", req.getUrgent());
// 可以在这里设置其他变量,如加急审批人ID
// variables.put("urgentApproverId", "指定用户ID");
String processInstanceId = newsWorkflowService.startApprovalProcess(req.getNewsId(), variables);
return AjaxResult.success(processInstanceId);
}
}
// WorkflowTaskController.java
@RestController
@RequestMapping("/workflow/task")
public class WorkflowTaskController {
@Autowired private TaskService taskService;
@Autowired
private NewsWorkflowService newsWorkflowService;
/**
* 获取当前用户的新闻相关待办 */
@GetMapping("/newsTodo")
public AjaxResult getNewsTodoTasks() {
Long userId = SecurityUtils.getUserId();
List<Task> tasks = newsWorkflowService.getTodoTasks(String.valueOf(userId));
// 可以进一步过滤只显示与新闻流程定义Key相关的任务 return AjaxResult.success(tasks);
}
/**
* 审批通过/驳回 */
@PostMapping("/complete")
public AjaxResult complete(@RequestBody CompleteTaskReq req) {
newsWorkflowService.completeTask(req.getTaskId(), req.getApprovalResult(), req.getComment());
return AjaxResult.success();
}
}
关键配置与检查点
- 数据库表 :确保Warm-Flow所需的表(以
flw_或act_为前缀)已正确创建并初始化。 - 依赖检查 :确认
ruoyi-workflow模块依赖(如warm-flow-spring-boot-starter)已正确引入项目pom.xml。 - 权限集成 :Warm-Flow已与Ruoyi的权限体系(用户、角色、部门)集成,在办理人策略中可直接使用
ISysUserService等若依服务进行人员查找。 - 流程变量 :加急判断
${news.urgent == true}依赖于流程变量news和urgent,确保在启动流程时正确传入。 - 网关配置 :在流程设计器中,排他网关(
urgent_gateway)的出口顺序流需正确设置条件表达式,以分别导向"加急审批"和"一级审批"节点。