【功能优化】工作流:BPMN 流程图高亮的计算,切换到后端为主
This commit is contained in:
parent
f299bf8a36
commit
41eec7806d
|
@ -1,11 +0,0 @@
|
|||
-- ----------------------------
|
||||
-- 流程抄送表新加流程活动编号
|
||||
-- ----------------------------
|
||||
ALTER TABLE `pro-test`.`bpm_process_instance_copy`
|
||||
ADD COLUMN `activity_id` varchar(64) NULL COMMENT '流程活动编号' AFTER `category`,
|
||||
MODIFY COLUMN `task_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '任务编号' AFTER `category`;
|
||||
|
||||
ALTER TABLE `pro-test`.`bpm_process_definition_info`
|
||||
ADD COLUMN `model_type` tinyint NOT NULL DEFAULT 10 COMMENT '流程模型的类型' AFTER `model_id`,
|
||||
ADD COLUMN `simple_model` json NULL COMMENT 'SIMPLE 设计器模型数据' AFTER `form_custom_view_path`,
|
||||
ADD COLUMN `visible` bit(1) NOT NULL DEFAULT 1 COMMENT '是否可见' AFTER `simple_model`;
|
|
@ -38,6 +38,10 @@ public enum BpmProcessInstanceStatusEnum implements IntArrayValuable {
|
|||
return ARRAYS;
|
||||
}
|
||||
|
||||
public static boolean isRejectStatus(Integer status) {
|
||||
return REJECT.getStatus().equals(status);
|
||||
}
|
||||
|
||||
public static boolean isProcessEndStatus(Integer status) {
|
||||
return ObjectUtils.equalsAny(status,
|
||||
APPROVE.getStatus(), REJECT.getStatus(), CANCEL.getStatus());
|
||||
|
|
|
@ -45,6 +45,10 @@ public enum BpmTaskStatusEnum {
|
|||
*/
|
||||
private final String name;
|
||||
|
||||
public static boolean isRejectStatus(Integer status) {
|
||||
return REJECT.getStatus().equals(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断该状态是否已经处于 End 最终状态
|
||||
* <p>
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
package cn.iocoder.yudao.module.bpm.controller.admin.task;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.convert.task.BpmActivityConvert;
|
||||
import cn.iocoder.yudao.module.bpm.service.task.BpmActivityService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 流程活动实例")
|
||||
@RestController
|
||||
@RequestMapping("/bpm/activity")
|
||||
@Validated
|
||||
public class BpmActivityController {
|
||||
|
||||
@Resource
|
||||
private BpmActivityService activityService;
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "生成指定流程实例的高亮流程图",
|
||||
description = "只高亮进行中的任务。不过要注意,该接口暂时没用,通过前端的 ProcessViewer.vue 界面的 highlightDiagram 方法生成")
|
||||
@Parameter(name = "processInstanceId", description = "流程实例的编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('bpm:task:query')")
|
||||
public CommonResult<List<BpmActivityRespVO>> getActivityList(
|
||||
@RequestParam("processInstanceId") String processInstanceId) {
|
||||
return success(BpmActivityConvert.INSTANCE.convertList(activityService.getActivityListByProcessInstanceId(processInstanceId)));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
### 请求 /bpm/process-instance/get-bpmn 接口 => 成功
|
||||
GET {{baseUrl}}/bpm/process-instance/get-bpmn-model-view?id=1d5fb5a6-85f8-11ef-b717-7e93075f94e3
|
||||
Content-Type: application/json
|
||||
tenant-id: 1
|
||||
Authorization: Bearer {{token}}
|
|
@ -173,4 +173,11 @@ public class BpmProcessInstanceController {
|
|||
return success(processInstanceService.getApprovalDetail(getLoginUserId(), reqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/get-bpmn-model-view")
|
||||
@Operation(summary = "获取流程实例的 BPMN 模型视图", description = "在【流程详细】界面中,进行调用")
|
||||
@Parameter(name = "id", description = "流程实例的编号", required = true)
|
||||
public CommonResult<BpmProcessInstanceBpmnModelViewRespVO> getProcessInstanceBpmnModelView(@RequestParam(value = "id") String id) {
|
||||
return success(processInstanceService.getProcessInstanceBpmnModelView(id));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ public class BpmTaskController {
|
|||
@PreAuthorize("@ss.hasPermission('bpm:task:query')")
|
||||
public CommonResult<List<BpmTaskRespVO>> getTaskListByProcessInstanceId(
|
||||
@RequestParam("processInstanceId") String processInstanceId) {
|
||||
List<HistoricTaskInstance> taskList = taskService.getTaskListByProcessInstanceId(processInstanceId);
|
||||
List<HistoricTaskInstance> taskList = taskService.getTaskListByProcessInstanceId(processInstanceId, true);
|
||||
if (CollUtil.isEmpty(taskList)) {
|
||||
return success(Collections.emptyList());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Schema(description = "管理后台 - 流程示例的 BPMN 视图 Response VO")
|
||||
@Data
|
||||
public class BpmProcessInstanceBpmnModelViewRespVO {
|
||||
|
||||
// ========== 基本信息 ==========
|
||||
|
||||
@Schema(description = "流程实例信息", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private BpmProcessInstanceRespVO processInstance;
|
||||
|
||||
@Schema(description = "任务列表", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<BpmTaskRespVO> tasks;
|
||||
|
||||
@Schema(description = "BPMN XML", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String bpmnXml;
|
||||
|
||||
// ========== 进度信息 ==========
|
||||
|
||||
@Schema(description = "进行中的活动节点编号集合", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Set<String> unfinishedTaskActivityIds; // 只包括 UserTask
|
||||
|
||||
@Schema(description = "已经完成的活动节点编号集合", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Set<String> finishedTaskActivityIds; // 包括 UserTask、Gateway 等,不包括 SequenceFlow
|
||||
|
||||
@Schema(description = "已经完成的连线节点编号集合", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Set<String> finishedSequenceFlowActivityIds; // 只包括 SequenceFlow
|
||||
|
||||
@Schema(description = "已经拒绝的活动节点编号集合", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Set<String> rejectedTaskActivityIds; // 只包括 UserTask
|
||||
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package cn.iocoder.yudao.module.bpm.convert.task;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
|
||||
import org.flowable.engine.history.HistoricActivityInstance;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* BPM 活动 Convert
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper(uses = DateUtils.class)
|
||||
public interface BpmActivityConvert {
|
||||
|
||||
BpmActivityConvert INSTANCE = Mappers.getMapper(BpmActivityConvert.class);
|
||||
|
||||
List<BpmActivityRespVO> convertList(List<HistoricActivityInstance> list);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(source = "activityId", target = "key"),
|
||||
@Mapping(source = "activityType", target = "type")
|
||||
})
|
||||
BpmActivityRespVO convert(HistoricActivityInstance bean);
|
||||
}
|
|
@ -1,23 +1,29 @@
|
|||
package cn.iocoder.yudao.module.bpm.convert.task;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceBpmnModelViewRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
|
||||
import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceStatusEvent;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
|
||||
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
|
||||
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.MappingTarget;
|
||||
|
@ -25,6 +31,9 @@ import org.mapstruct.factory.Mappers;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
/**
|
||||
* 流程实例 Convert
|
||||
|
@ -109,4 +118,49 @@ public interface BpmProcessInstanceConvert {
|
|||
.setStartUserId(NumberUtils.parseLong(instance.getStartUserId()));
|
||||
}
|
||||
|
||||
default BpmProcessInstanceBpmnModelViewRespVO buildProcessInstanceBpmnModelView(HistoricProcessInstance processInstance,
|
||||
List<HistoricTaskInstance> taskInstances,
|
||||
BpmnModel bpmnModel,
|
||||
Set<String> unfinishedTaskActivityIds,
|
||||
Set<String> finishedTaskActivityIds,
|
||||
Set<String> finishedSequenceFlowActivityIds,
|
||||
Set<String> rejectTaskActivityIds,
|
||||
Map<Long, AdminUserRespDTO> userMap,
|
||||
Map<Long, DeptRespDTO> deptMap) {
|
||||
BpmProcessInstanceBpmnModelViewRespVO respVO = new BpmProcessInstanceBpmnModelViewRespVO();
|
||||
// 基本信息
|
||||
respVO.setProcessInstance(BeanUtils.toBean(processInstance, BpmProcessInstanceRespVO.class, o -> o
|
||||
.setStatus(FlowableUtils.getProcessInstanceStatus(processInstance)))
|
||||
.setStartUser(buildUser(processInstance.getStartUserId(), userMap, deptMap)));
|
||||
respVO.setTasks(convertList(taskInstances, task -> BeanUtils.toBean(task, BpmTaskRespVO.class)
|
||||
.setStatus(FlowableUtils.getTaskStatus(task)).setReason(FlowableUtils.getTaskReason(task))
|
||||
.setAssigneeUser(buildUser(task.getAssignee(), userMap, deptMap))
|
||||
.setOwnerUser(buildUser(task.getOwner(), userMap, deptMap))));
|
||||
respVO.setBpmnXml(BpmnModelUtils.getBpmnXml(bpmnModel));
|
||||
// 进度信息
|
||||
respVO.setUnfinishedTaskActivityIds(unfinishedTaskActivityIds)
|
||||
.setFinishedTaskActivityIds(finishedTaskActivityIds)
|
||||
.setFinishedSequenceFlowActivityIds(finishedSequenceFlowActivityIds)
|
||||
.setRejectedTaskActivityIds(rejectTaskActivityIds);
|
||||
return respVO;
|
||||
}
|
||||
|
||||
default BpmProcessInstanceRespVO.User buildUser(String userId,
|
||||
Map<Long, AdminUserRespDTO> userMap,
|
||||
Map<Long, DeptRespDTO> deptMap) {
|
||||
if (StrUtil.isBlank(userId)) {
|
||||
return null;
|
||||
}
|
||||
AdminUserRespDTO user = userMap.get(NumberUtils.parseLong(userId));
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
BpmProcessInstanceRespVO.User userVO = BeanUtils.toBean(user, BpmProcessInstanceRespVO.User.class);
|
||||
DeptRespDTO dept = user.getDeptId() != null ? deptMap.get(user.getDeptId()) : null;
|
||||
if (dept != null) {
|
||||
userVO.setDeptName(dept.getName());
|
||||
}
|
||||
return userVO;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import org.springframework.validation.annotation.Validated;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
// TODO 芋艿:准备废弃
|
||||
/**
|
||||
* BPM 活动实例 Service 实现类
|
||||
*
|
||||
|
|
|
@ -104,6 +104,14 @@ public interface BpmProcessInstanceService {
|
|||
*/
|
||||
BpmApprovalDetailRespVO getApprovalDetail(Long loginUserId, @Valid BpmApprovalDetailReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 获取流程实例的 BPMN 模型视图
|
||||
*
|
||||
* @param id 流程实例的编号
|
||||
* @return BPMN 模型视图
|
||||
*/
|
||||
BpmProcessInstanceBpmnModelViewRespVO getProcessInstanceBpmnModelView(String id);
|
||||
|
||||
// ========== Update 写入相关方法 ==========
|
||||
|
||||
/**
|
||||
|
@ -157,5 +165,4 @@ public interface BpmProcessInstanceService {
|
|||
*/
|
||||
void processProcessInstanceCompleted(ProcessInstance instance);
|
||||
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -73,9 +73,10 @@ public interface BpmTaskService {
|
|||
* 获得指定流程实例的流程任务列表,包括所有状态的
|
||||
*
|
||||
* @param processInstanceId 流程实例的编号
|
||||
* @param asc 是否升序
|
||||
* @return 流程任务列表
|
||||
*/
|
||||
List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId);
|
||||
List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId, Boolean asc);
|
||||
|
||||
/**
|
||||
* 获取任务
|
||||
|
|
|
@ -170,16 +170,16 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId) {
|
||||
List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
|
||||
public List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId, Boolean asc) {
|
||||
HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery()
|
||||
.includeTaskLocalVariables()
|
||||
.processInstanceId(processInstanceId)
|
||||
.orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序
|
||||
.list();
|
||||
if (CollUtil.isEmpty(tasks)) {
|
||||
return Collections.emptyList();
|
||||
.processInstanceId(processInstanceId);
|
||||
if (Boolean.TRUE.equals(asc)) {
|
||||
query.orderByHistoricTaskInstanceStartTime().asc();
|
||||
} else {
|
||||
query.orderByHistoricTaskInstanceStartTime().desc();
|
||||
}
|
||||
return tasks;
|
||||
return query.list();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue