【功能优化】工作流: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;
|
return ARRAYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isRejectStatus(Integer status) {
|
||||||
|
return REJECT.getStatus().equals(status);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isProcessEndStatus(Integer status) {
|
public static boolean isProcessEndStatus(Integer status) {
|
||||||
return ObjectUtils.equalsAny(status,
|
return ObjectUtils.equalsAny(status,
|
||||||
APPROVE.getStatus(), REJECT.getStatus(), CANCEL.getStatus());
|
APPROVE.getStatus(), REJECT.getStatus(), CANCEL.getStatus());
|
||||||
|
|
|
@ -45,6 +45,10 @@ public enum BpmTaskStatusEnum {
|
||||||
*/
|
*/
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
public static boolean isRejectStatus(Integer status) {
|
||||||
|
return REJECT.getStatus().equals(status);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断该状态是否已经处于 End 最终状态
|
* 判断该状态是否已经处于 End 最终状态
|
||||||
* <p>
|
* <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));
|
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')")
|
@PreAuthorize("@ss.hasPermission('bpm:task:query')")
|
||||||
public CommonResult<List<BpmTaskRespVO>> getTaskListByProcessInstanceId(
|
public CommonResult<List<BpmTaskRespVO>> getTaskListByProcessInstanceId(
|
||||||
@RequestParam("processInstanceId") String processInstanceId) {
|
@RequestParam("processInstanceId") String processInstanceId) {
|
||||||
List<HistoricTaskInstance> taskList = taskService.getTaskListByProcessInstanceId(processInstanceId);
|
List<HistoricTaskInstance> taskList = taskService.getTaskListByProcessInstanceId(processInstanceId, true);
|
||||||
if (CollUtil.isEmpty(taskList)) {
|
if (CollUtil.isEmpty(taskList)) {
|
||||||
return success(Collections.emptyList());
|
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;
|
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.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
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.number.NumberUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
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.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.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.BpmCategoryDO;
|
||||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
|
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
|
||||||
import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceStatusEvent;
|
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.framework.flowable.core.util.FlowableUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
|
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.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO;
|
||||||
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
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.history.HistoricProcessInstance;
|
||||||
import org.flowable.engine.repository.ProcessDefinition;
|
import org.flowable.engine.repository.ProcessDefinition;
|
||||||
import org.flowable.engine.runtime.ProcessInstance;
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
import org.flowable.task.api.Task;
|
import org.flowable.task.api.Task;
|
||||||
|
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.Mapping;
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.MappingTarget;
|
import org.mapstruct.MappingTarget;
|
||||||
|
@ -25,6 +31,9 @@ import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 流程实例 Convert
|
* 流程实例 Convert
|
||||||
|
@ -109,4 +118,49 @@ public interface BpmProcessInstanceConvert {
|
||||||
.setStartUserId(NumberUtils.parseLong(instance.getStartUserId()));
|
.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;
|
import java.util.List;
|
||||||
|
|
||||||
|
// TODO 芋艿:准备废弃
|
||||||
/**
|
/**
|
||||||
* BPM 活动实例 Service 实现类
|
* BPM 活动实例 Service 实现类
|
||||||
*
|
*
|
||||||
|
|
|
@ -104,6 +104,14 @@ public interface BpmProcessInstanceService {
|
||||||
*/
|
*/
|
||||||
BpmApprovalDetailRespVO getApprovalDetail(Long loginUserId, @Valid BpmApprovalDetailReqVO reqVO);
|
BpmApprovalDetailRespVO getApprovalDetail(Long loginUserId, @Valid BpmApprovalDetailReqVO reqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取流程实例的 BPMN 模型视图
|
||||||
|
*
|
||||||
|
* @param id 流程实例的编号
|
||||||
|
* @return BPMN 模型视图
|
||||||
|
*/
|
||||||
|
BpmProcessInstanceBpmnModelViewRespVO getProcessInstanceBpmnModelView(String id);
|
||||||
|
|
||||||
// ========== Update 写入相关方法 ==========
|
// ========== Update 写入相关方法 ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,5 +165,4 @@ public interface BpmProcessInstanceService {
|
||||||
*/
|
*/
|
||||||
void processProcessInstanceCompleted(ProcessInstance instance);
|
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 processInstanceId 流程实例的编号
|
||||||
|
* @param asc 是否升序
|
||||||
* @return 流程任务列表
|
* @return 流程任务列表
|
||||||
*/
|
*/
|
||||||
List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId);
|
List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId, Boolean asc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取任务
|
* 获取任务
|
||||||
|
|
|
@ -170,16 +170,16 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId) {
|
public List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId, Boolean asc) {
|
||||||
List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
|
HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery()
|
||||||
.includeTaskLocalVariables()
|
.includeTaskLocalVariables()
|
||||||
.processInstanceId(processInstanceId)
|
.processInstanceId(processInstanceId);
|
||||||
.orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序
|
if (Boolean.TRUE.equals(asc)) {
|
||||||
.list();
|
query.orderByHistoricTaskInstanceStartTime().asc();
|
||||||
if (CollUtil.isEmpty(tasks)) {
|
} else {
|
||||||
return Collections.emptyList();
|
query.orderByHistoricTaskInstanceStartTime().desc();
|
||||||
}
|
}
|
||||||
return tasks;
|
return query.list();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue