Merge remote-tracking branch 'origin/master'
Some checks failed
Java CI with Maven / build (11) (push) Has been cancelled
Java CI with Maven / build (17) (push) Has been cancelled
Java CI with Maven / build (8) (push) Has been cancelled
yudao-ui-admin CI / build (14.x) (push) Has been cancelled
yudao-ui-admin CI / build (16.x) (push) Has been cancelled

This commit is contained in:
XaoLi717 2025-01-26 14:25:44 +08:00
commit e8d8233ba0
26 changed files with 912 additions and 46 deletions

View File

@ -102,7 +102,8 @@ public interface ErrorCodeConstants {
ErrorCode PROCESS_KEY_NOT_PROVIDED = new ErrorCode(1_009_022_001, "工作流表单key没有提供"); ErrorCode PROCESS_KEY_NOT_PROVIDED = new ErrorCode(1_009_022_001, "工作流表单key没有提供");
// ========== BPM 流程实例信息 1_009_023_000 ========== // ========== BPM 流程实例信息 1_009_023_000 ==========
ErrorCode PROCESS_INSTANCE_TODO_NOT_EXISTS = new ErrorCode(1_009_023_000, "BPM 流程实例信息不存在"); ErrorCode PROCESS_INSTANCE_TODO_NOT_EXISTS = new ErrorCode(1_009_023_000, "BPM 流程实例信息不存在");
// ========== BPM 流转记录扩展 1_009_024_000 ==========
ErrorCode TASK_EXTEND_RECORD_NOT_EXISTS = new ErrorCode(1_009_024_000, "BPM 流转记录扩展不存在");
// ========== only 1_011_013_000 ========== // ========== only 1_011_013_000 ==========
ErrorCode DOC_FILE_NOT_EXISTS = new ErrorCode(1_011_013_000, "目标文档不存在"); ErrorCode DOC_FILE_NOT_EXISTS = new ErrorCode(1_011_013_000, "目标文档不存在");

View File

@ -127,7 +127,7 @@ public class BpmModelController {
} }
byte[] bpmnBytes = modelService.getModelBpmnXML(id); byte[] bpmnBytes = modelService.getModelBpmnXML(id);
BpmSimpleModelNodeVO simpleModel = modelService.getSimpleModel(id); BpmSimpleModelNodeVO simpleModel = modelService.getSimpleModel(id);
return success(BpmModelConvert.INSTANCE.buildModel(model, bpmnBytes, simpleModel)); return success( BpmModelConvert.INSTANCE.buildModel(model, bpmnBytes, simpleModel) );
} }
@PostMapping("/create") @PostMapping("/create")

View File

@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;

View File

@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
@ -12,6 +13,7 @@ import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService;
import cn.iocoder.yudao.module.bpm.service.processinstancetodo.ProcessInstanceTodoService; import cn.iocoder.yudao.module.bpm.service.processinstancetodo.ProcessInstanceTodoService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
import cn.iocoder.yudao.module.bpm.service.taskextendrecord.TaskTransitionLog;
import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.DeptApi;
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.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
@ -143,7 +145,30 @@ public class BpmTaskController {
return success(BpmTaskConvert.INSTANCE.buildTaskListByProcessInstanceId(taskList, return success(BpmTaskConvert.INSTANCE.buildTaskListByProcessInstanceId(taskList,
formMap, userMap, deptMap)); formMap, userMap, deptMap));
} }
@GetMapping("/list-by-process-instance-id2")
@Operation(summary = "获得指定流程实例的任务列表", description = "包括完成的、未完成的")
@Parameter(name = "processInstanceId", description = "流程实例的编号", required = true)
@PreAuthorize("@ss.hasPermission('bpm:task:query')")
public CommonResult<List<BpmTaskRespVO>> getTaskListByProcessInstanceId2(
@RequestParam("processInstanceId") String processInstanceId) {
//List<HistoricTaskInstance> taskList = taskService.getTaskListByProcessInstanceId(processInstanceId, true);
List<TaskTransitionLog> taskList = taskService.getTaskListByProcessInstanceId2(processInstanceId, true);
if (CollUtil.isEmpty(taskList)) {
return success(Collections.emptyList());
}
// 拼接数据
Set<Long> userIds = convertSetByFlatMap(taskList, task ->
Stream.of(NumberUtils.parseLong(task.getUserId()), NumberUtils.parseLong(task.getUserId())));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(
convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
// 获得 Form Map
Map<Long, BpmFormDO> formMap = formService.getFormMap(
convertSet(taskList, task -> NumberUtils.parseLong(task.getFormKey())));
return success(BpmTaskConvert.INSTANCE.buildTaskListByProcessInstanceId2(taskList,
formMap, userMap, deptMap));
}
@PutMapping("/approve") @PutMapping("/approve")
@Operation(summary = "通过任务") @Operation(summary = "通过任务")
@PreAuthorize("@ss.hasPermission('bpm:task:update')") @PreAuthorize("@ss.hasPermission('bpm:task:update')")

View File

@ -0,0 +1,95 @@
package cn.iocoder.yudao.module.bpm.controller.admin.taskextendrecord;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.bpm.controller.admin.taskextendrecord.vo.*;
import cn.iocoder.yudao.module.bpm.dal.dataobject.taskextendrecord.TaskExtendRecordDO;
import cn.iocoder.yudao.module.bpm.service.taskextendrecord.TaskExtendRecordService;
@Tag(name = "管理后台 - BPM 流转记录扩展")
@RestController
@RequestMapping("/bpm/task-extend-record")
@Validated
public class TaskExtendRecordController {
@Resource
private TaskExtendRecordService taskExtendRecordService;
@PostMapping("/create")
@Operation(summary = "创建BPM 流转记录扩展")
@PreAuthorize("@ss.hasPermission('bpm:task-extend-record:create')")
public CommonResult<Long> createTaskExtendRecord(@Valid @RequestBody TaskExtendRecordSaveReqVO createReqVO) {
return success(taskExtendRecordService.createTaskExtendRecord(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新BPM 流转记录扩展")
@PreAuthorize("@ss.hasPermission('bpm:task-extend-record:update')")
public CommonResult<Boolean> updateTaskExtendRecord(@Valid @RequestBody TaskExtendRecordSaveReqVO updateReqVO) {
taskExtendRecordService.updateTaskExtendRecord(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除BPM 流转记录扩展")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('bpm:task-extend-record:delete')")
public CommonResult<Boolean> deleteTaskExtendRecord(@RequestParam("id") Long id) {
taskExtendRecordService.deleteTaskExtendRecord(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得BPM 流转记录扩展")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('bpm:task-extend-record:query')")
public CommonResult<TaskExtendRecordRespVO> getTaskExtendRecord(@RequestParam("id") Long id) {
TaskExtendRecordDO taskExtendRecord = taskExtendRecordService.getTaskExtendRecord(id);
return success(BeanUtils.toBean(taskExtendRecord, TaskExtendRecordRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得BPM 流转记录扩展分页")
@PreAuthorize("@ss.hasPermission('bpm:task-extend-record:query')")
public CommonResult<PageResult<TaskExtendRecordRespVO>> getTaskExtendRecordPage(@Valid TaskExtendRecordPageReqVO pageReqVO) {
PageResult<TaskExtendRecordDO> pageResult = taskExtendRecordService.getTaskExtendRecordPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, TaskExtendRecordRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出BPM 流转记录扩展 Excel")
@PreAuthorize("@ss.hasPermission('bpm:task-extend-record:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportTaskExtendRecordExcel(@Valid TaskExtendRecordPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<TaskExtendRecordDO> list = taskExtendRecordService.getTaskExtendRecordPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "BPM 流转记录扩展.xls", "数据", TaskExtendRecordRespVO.class,
BeanUtils.toBean(list, TaskExtendRecordRespVO.class));
}
}

View File

@ -0,0 +1,66 @@
package cn.iocoder.yudao.module.bpm.controller.admin.taskextendrecord.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - BPM 流转记录扩展分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TaskExtendRecordPageReqVO extends PageParam {
@Schema(description = "任务id", example = "12523")
private String taskId;
@Schema(description = "任务名称", example = "李四")
private String taskName;
@Schema(description = "开始时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] startTime;
@Schema(description = "结束时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] endTime;
@Schema(description = "用户id", example = "13977")
private String userId;
@Schema(description = "用户名称", example = "张三")
private String userName;
@Schema(description = "意见", example = "不对")
private String reason;
@Schema(description = "持续时间")
private Long duration;
@Schema(description = "工作时间")
private Long workTime;
@Schema(description = "流程实例id", example = "1932")
private String processInstanceId;
@Schema(description = "备用字段1")
private String field1;
@Schema(description = "备用字段2")
private String field2;
@Schema(description = "备用字段3")
private String field3;
@Schema(description = "审批状态", example = "1")
private Integer status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,79 @@
package cn.iocoder.yudao.module.bpm.controller.admin.taskextendrecord.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - BPM 流转记录扩展 Response VO")
@Data
@ExcelIgnoreUnannotated
public class TaskExtendRecordRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6915")
@ExcelProperty("编号")
private Long id;
@Schema(description = "任务id", example = "12523")
@ExcelProperty("任务id")
private String taskId;
@Schema(description = "任务名称", example = "李四")
@ExcelProperty("任务名称")
private String taskName;
@Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("开始时间")
private LocalDateTime startTime;
@Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("结束时间")
private LocalDateTime endTime;
@Schema(description = "用户id", example = "13977")
@ExcelProperty("用户id")
private String userId;
@Schema(description = "用户名称", example = "张三")
@ExcelProperty("用户名称")
private String userName;
@Schema(description = "意见", requiredMode = Schema.RequiredMode.REQUIRED, example = "不对")
@ExcelProperty("意见")
private String reason;
@Schema(description = "持续时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("持续时间")
private Long duration;
@Schema(description = "工作时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("工作时间")
private Long workTime;
@Schema(description = "流程实例id", example = "1932")
@ExcelProperty("流程实例id")
private String processInstanceId;
@Schema(description = "备用字段1")
@ExcelProperty("备用字段1")
private String field1;
@Schema(description = "备用字段2")
@ExcelProperty("备用字段2")
private String field2;
@Schema(description = "备用字段3")
@ExcelProperty("备用字段3")
private String field3;
@Schema(description = "审批状态", example = "1")
@ExcelProperty("审批状态")
private Integer status;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,64 @@
package cn.iocoder.yudao.module.bpm.controller.admin.taskextendrecord.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - BPM 流转记录扩展新增/修改 Request VO")
@Data
public class TaskExtendRecordSaveReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6915")
private Long id;
@Schema(description = "任务id", example = "12523")
private String taskId;
@Schema(description = "任务名称", example = "李四")
private String taskName;
@Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "开始时间不能为空")
private LocalDateTime startTime;
@Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "结束时间不能为空")
private LocalDateTime endTime;
@Schema(description = "用户id", example = "13977")
private String userId;
@Schema(description = "用户名称", example = "张三")
private String userName;
@Schema(description = "意见", requiredMode = Schema.RequiredMode.REQUIRED, example = "不对")
@NotEmpty(message = "意见不能为空")
private String reason;
@Schema(description = "持续时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "持续时间不能为空")
private Long duration;
@Schema(description = "工作时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "工作时间不能为空")
private Long workTime;
@Schema(description = "流程实例id", example = "1932")
private String processInstanceId;
@Schema(description = "备用字段1")
private String field1;
@Schema(description = "备用字段2")
private String field2;
@Schema(description = "备用字段3")
private String field3;
@Schema(description = "审批状态", example = "1")
private Integer status;
}

View File

@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.processinstancetodo.ProcessIns
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
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.BpmMessageSendWhenTaskCreatedReqDTO; import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
import cn.iocoder.yudao.module.bpm.service.taskextendrecord.TaskTransitionLog;
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.engine.history.HistoricProcessInstance; import org.flowable.engine.history.HistoricProcessInstance;
@ -119,6 +120,34 @@ public interface BpmTaskConvert {
return taskVO; return taskVO;
}); });
} }
default List<BpmTaskRespVO> buildTaskListByProcessInstanceId2(List<TaskTransitionLog> taskList,
Map<Long, BpmFormDO> formMap,
Map<Long, AdminUserRespDTO> userMap,
Map<Long, DeptRespDTO> deptMap) {
return CollectionUtils.convertList(taskList, task -> {
// 特殊已取消的任务不返回
BpmTaskRespVO taskVO = BeanUtils.toBean(task, BpmTaskRespVO.class);
Integer taskStatus = task.getStatus();
if (BpmTaskStatusEnum.isCancelStatus(taskStatus)) {
return null;
}
taskVO.setStatus(taskStatus).setReason(task.getReason() );
// 表单信息
BpmFormDO form = MapUtil.get(formMap, NumberUtils.parseLong(task.getFormKey()), BpmFormDO.class);
if (form != null) {
// taskVO.setFormId(form.getId()).setFormName(form.getName()).setFormConf(form.getConf())
// .setFormFields(form.getFields()).setFormVariables(FlowableUtils.getTaskFormVariable(task));
}
// 用户信息
// buildTaskAssignee(taskVO, task.getAssignee(), userMap, deptMap);
// buildTaskOwner(taskVO, task.getOwner(), userMap, deptMap);
buildTaskAssignee(taskVO, task.getUserId(), userMap, deptMap);
buildTaskOwner(taskVO, task.getUserId(), userMap, deptMap);
return taskVO;
});
}
default PageResult<BpmTaskRespVO> buildTaskPageNew(PageResult<HistoricTaskInstance> pageResult, default PageResult<BpmTaskRespVO> buildTaskPageNew(PageResult<HistoricTaskInstance> pageResult,
Map<String, HistoricProcessInstance> processInstanceMap, Map<String, HistoricProcessInstance> processInstanceMap,

View File

@ -0,0 +1,89 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.taskextendrecord;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* BPM 流转记录扩展 DO
*
* @author 君风
*/
@TableName("bpm_task_extend_record")
@KeySequence("bpm_task_extend_record_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TaskExtendRecordDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 任务id
*/
private String taskId;
/**
* 任务名称
*/
private String taskName;
/**
* 开始时间
*/
private LocalDateTime startTime;
/**
* 结束时间
*/
private LocalDateTime endTime;
/**
* 用户id
*/
private String userId;
/**
* 用户名称
*/
private String userName;
/**
* 意见
*/
private String reason;
/**
* 持续时间
*/
private Long duration;
/**
* 工作时间
*/
private Long workTime;
/**
* 流程实例id
*/
private String processInstanceId;
/**
* 备用字段1
*/
private String field1;
/**
* 备用字段2
*/
private String field2;
/**
* 备用字段3
*/
private String field3;
/**
* 审批状态
*/
private Integer status;
}

View File

@ -0,0 +1,48 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.taskextendrecord;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.bpm.dal.dataobject.taskextendrecord.TaskExtendRecordDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.bpm.controller.admin.taskextendrecord.vo.*;
/**
* BPM 流转记录扩展 Mapper
*
* @author 君风
*/
@Mapper
public interface TaskExtendRecordMapper extends BaseMapperX<TaskExtendRecordDO> {
default PageResult<TaskExtendRecordDO> selectPage(TaskExtendRecordPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<TaskExtendRecordDO>()
.eqIfPresent(TaskExtendRecordDO::getTaskId, reqVO.getTaskId())
.likeIfPresent(TaskExtendRecordDO::getTaskName, reqVO.getTaskName())
.betweenIfPresent(TaskExtendRecordDO::getStartTime, reqVO.getStartTime())
.betweenIfPresent(TaskExtendRecordDO::getEndTime, reqVO.getEndTime())
.eqIfPresent(TaskExtendRecordDO::getUserId, reqVO.getUserId())
.likeIfPresent(TaskExtendRecordDO::getUserName, reqVO.getUserName())
.eqIfPresent(TaskExtendRecordDO::getReason, reqVO.getReason())
.eqIfPresent(TaskExtendRecordDO::getDuration, reqVO.getDuration())
.eqIfPresent(TaskExtendRecordDO::getWorkTime, reqVO.getWorkTime())
.eqIfPresent(TaskExtendRecordDO::getProcessInstanceId, reqVO.getProcessInstanceId())
.eqIfPresent(TaskExtendRecordDO::getField1, reqVO.getField1())
.eqIfPresent(TaskExtendRecordDO::getField2, reqVO.getField2())
.eqIfPresent(TaskExtendRecordDO::getField3, reqVO.getField3())
.eqIfPresent(TaskExtendRecordDO::getStatus, reqVO.getStatus())
.betweenIfPresent(TaskExtendRecordDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(TaskExtendRecordDO::getId));
}
// 根据任务 ID 查询扩展记录
default List<TaskExtendRecordDO> getRecordsByProcessInstanceId(String processInstanceId) {
return selectList(new LambdaQueryWrapperX<TaskExtendRecordDO>()
.eq(TaskExtendRecordDO::getProcessInstanceId, processInstanceId)
.eq(TaskExtendRecordDO::getDeleted, 0) // 确保只查询未删除的记录
.orderByDesc(TaskExtendRecordDO::getCreateTime)); // 按照创建时间降序排列
}
}

View File

@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutHandlerTypeEnum; import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutHandlerTypeEnum;
import cn.iocoder.yudao.module.bpm.service.taskextendrecord.TaskTransitionLog;
import org.flowable.bpmn.model.UserTask; import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.history.HistoricActivityInstance; import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.task.api.Task; import org.flowable.task.api.Task;
@ -87,8 +88,8 @@ public interface BpmTaskService {
* @param asc 是否升序 * @param asc 是否升序
* @return 流程任务列表 * @return 流程任务列表
*/ */
List<TaskTransitionLog> getTaskListByProcessInstanceId2(String processInstanceId, Boolean asc);
List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId, Boolean asc); List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId, Boolean asc);
/** /**
* 获取任务 * 获取任务
* *

View File

@ -9,10 +9,12 @@ import cn.iocoder.yudao.framework.common.util.date.DateUtils;
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.ObjectUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.common.util.object.PageUtils; import cn.iocoder.yudao.framework.common.util.object.PageUtils;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.taskextendrecord.TaskExtendRecordDO;
import cn.iocoder.yudao.module.bpm.enums.definition.*; import cn.iocoder.yudao.module.bpm.enums.definition.*;
import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
@ -26,15 +28,14 @@ import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskTimeoutReqDTO; import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskTimeoutReqDTO;
import cn.iocoder.yudao.module.bpm.service.taskextendrecord.TaskExtendRecordService;
import cn.iocoder.yudao.module.bpm.service.taskextendrecord.TaskTransitionLog;
import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.DeptApi;
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.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.EndEvent;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.*; import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance; import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.runtime.ProcessInstance; import org.flowable.engine.runtime.ProcessInstance;
@ -53,8 +54,13 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -102,6 +108,9 @@ public class BpmTaskServiceImpl implements BpmTaskService {
@Resource @Resource
private RepositoryService repositoryService; private RepositoryService repositoryService;
@Resource
private TaskExtendRecordService taskExtendRecordService;
// ========== Query 查询相关方法 ========== // ========== Query 查询相关方法 ==========
@Override @Override
@ -225,9 +234,9 @@ public class BpmTaskServiceImpl implements BpmTaskService {
} }
return taskService.createTaskQuery().processInstanceIdIn(processInstanceIds).list(); return taskService.createTaskQuery().processInstanceIdIn(processInstanceIds).list();
} }
@Override @Override
public List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId, Boolean asc) { public List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId, Boolean asc) {
// 1. 获取 Flowable 历史任务记录
HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery() HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery()
.includeTaskLocalVariables() .includeTaskLocalVariables()
.processInstanceId(processInstanceId); .processInstanceId(processInstanceId);
@ -236,7 +245,84 @@ public class BpmTaskServiceImpl implements BpmTaskService {
} else { } else {
query.orderByHistoricTaskInstanceStartTime().desc(); query.orderByHistoricTaskInstanceStartTime().desc();
} }
return query.list(); List<HistoricTaskInstance> historicTasks = query.list();
return historicTasks;
}
@Override
public List<TaskTransitionLog> getTaskListByProcessInstanceId2(String processInstanceId, Boolean asc) {
// 1. 获取 Flowable 历史任务记录
HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery()
.includeTaskLocalVariables()
.processInstanceId(processInstanceId);
if (Boolean.TRUE.equals(asc)) {
query.orderByHistoricTaskInstanceStartTime().asc();
} else {
query.orderByHistoricTaskInstanceStartTime().desc();
}
List<HistoricTaskInstance> historicTasks = query.list();
// 2.获取所有相关的扩展记录
List<TaskExtendRecordDO> relatedRecords = taskExtendRecordService.getTaskExtendRecordsByProcessInstanceId(processInstanceId);
// 3. 转换 TaskExtendRecordDO TaskTransitionLog
List<TaskTransitionLog> transitionLogs = relatedRecords.stream()
.map(record -> {
TaskTransitionLog log = new TaskTransitionLog();
log.setId(record.getTaskId());
log.setName(record.getTaskName());
log.setUserId(record.getUserId());
log.setUserName(record.getUserName());
log.setCreateTime(record.getStartTime()); // 使用 startTime 作为时间戳
log.setEndTime(record.getEndTime());
log.setReason(record.getReason());
if ( record.getStatus() != null ) {
log.setStatus(record.getStatus());
}
if ( record.getDuration() != null ) {
log.setDurationInMillis( record.getDuration() );
}
return log;
}).collect(Collectors.toList());
// 4. historicTasks 转换为 TaskTransitionLog
List<TaskTransitionLog> taskLogs = historicTasks.stream()
.map(task -> {
TaskTransitionLog log = new TaskTransitionLog();
log.setId( task.getId() );
log.setName( task.getName() );
log.setUserId( task.getAssignee());
log.setReason( FlowableUtils.getTaskReason(task) ); // 可以从评论或其他字段获取具体原因
//startTime-------------------- Date 转换为 LocalDateTime
Date startDate = task.getStartTime();
if ( startDate != null ) {
LocalDateTime startTime = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
log.setCreateTime(startTime);
}
//endTime---------------------- Date 转换为 LocalDateTime
Date endDate = task.getEndTime();
if ( endDate != null) {
LocalDateTime endTime = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
log.setEndTime( endTime );
}
log.setFormKey( task.getFormKey() );
log.setStatus( FlowableUtils.getTaskStatus(task) );
if ( task.getDurationInMillis() != null ) {
log.setDurationInMillis( task.getDurationInMillis() );
}
return log;
}).collect(Collectors.toList());
// 5. 合并流转记录和任务记录
List<TaskTransitionLog> allLogs = new ArrayList<>();
allLogs.addAll(transitionLogs); // 加入扩展记录
allLogs.addAll(taskLogs); // 加入历史任务记录
// 6. 按时间排序所有记录升序
allLogs.sort(Comparator.comparing(TaskTransitionLog::getCreateTime).thenComparing(TaskTransitionLog::getEndTime));
return allLogs;
} }
/** /**
@ -309,13 +395,51 @@ public class BpmTaskServiceImpl implements BpmTaskService {
// 2.1 查询该任务的前置任务节点的 key 集合 // 2.1 查询该任务的前置任务节点的 key 集合
List<UserTask> previousUserList = BpmnModelUtils.getPreviousUserTaskList(source, null, null); List<UserTask> previousUserList = BpmnModelUtils.getPreviousUserTaskList(source, null, null);
if (CollUtil.isEmpty(previousUserList)) { if (CollUtil.isEmpty(previousUserList)) {
return Collections.emptyList(); //return Collections.emptyList();
} }
// 2.2 过滤只有串行可到达的节点才可以退回类似非串行子流程无法退回 // 2.2 过滤只有串行可到达的节点才可以退回类似非串行子流程无法退回
previousUserList.removeIf(userTask -> !BpmnModelUtils.isSequentialReachable(source, userTask, null)); previousUserList.removeIf(userTask -> !BpmnModelUtils.isSequentialReachable(source, userTask, null));
// 3. 获取流程模型中的起始节点开始事件
// FlowElement startElement = getStartEvent(bpmnModel);
// if (startElement != null) {
// // 将起始节点信息转换为 UserTask 对象
// UserTask startUserTask = new UserTask();
// startUserTask.setId(startElement.getId()); // 设置起始节点 ID
// if (startElement.getName().equals("")) {
// startUserTask.setName("开始");
// }else{
// startUserTask.setName(startElement.getName()); // 设置起始节点名称
// }
// startUserTask.setAssignee(""); // 可以为空通常起始节点不直接关联任务的处理人
// startUserTask.setCategory("StartEvent"); // 设置类别为 StartEvent表示这是一个起始节点
//
// // 添加起始节点到 previousUserList
// previousUserList.add(startUserTask);
// // 打印或者记录起始节点信息
// //System.out.println("起始节点: " + startElement.getId() + " - " + startElement.getName());
// }
return previousUserList; return previousUserList;
} }
/**
* 获取流程模型中的起始节点开始事件
*
* @param bpmnModel 流程模型
* @return 起始节点
*/
private FlowElement getStartEvent(BpmnModel bpmnModel) {
System.out.println("getStartEvent");
// 获取流程的开始事件通常是第一个节点
for (FlowElement flowElement : bpmnModel.getMainProcess().getFlowElements()) {
if (flowElement instanceof StartEvent) {
System.out.println(flowElement);
return flowElement;
}
}
return null; // 如果没有找到起始事件返回 null
}
@Override @Override
public <T extends TaskInfo> List<T> getAllChildrenTaskListByParentTaskId(String parentTaskId, List<T> tasks) { public <T extends TaskInfo> List<T> getAllChildrenTaskListByParentTaskId(String parentTaskId, List<T> tasks) {
if (CollUtil.isEmpty(tasks)) { if (CollUtil.isEmpty(tasks)) {
@ -764,13 +888,13 @@ public class BpmTaskServiceImpl implements BpmTaskService {
.moveExecutionsToSingleActivityId(runExecutionIds, reqVO.getTargetTaskDefinitionKey()) .moveExecutionsToSingleActivityId(runExecutionIds, reqVO.getTargetTaskDefinitionKey())
.changeState(); .changeState();
} }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void delegateTask(Long userId, BpmTaskDelegateReqVO reqVO) { public void delegateTask(Long userId, BpmTaskDelegateReqVO reqVO) {
String taskId = reqVO.getId(); String taskId = reqVO.getId();
// 1.1 校验任务 // 1.1 校验任务
Task task = validateTask(userId, reqVO.getId()); Task task = validateTask(userId, reqVO.getId());
Date startDate = task.getCreateTime();
if (task.getAssignee().equals(reqVO.getDelegateUserId().toString())) { // 校验当前审批人和被委派人不是同一人 if (task.getAssignee().equals(reqVO.getDelegateUserId().toString())) { // 校验当前审批人和被委派人不是同一人
throw exception(TASK_DELEGATE_FAIL_USER_REPEAT); throw exception(TASK_DELEGATE_FAIL_USER_REPEAT);
} }
@ -790,13 +914,34 @@ public class BpmTaskServiceImpl implements BpmTaskService {
// 3.2 执行委派将任务委派给 delegateUser // 3.2 执行委派将任务委派给 delegateUser
taskService.delegateTask(taskId, reqVO.getDelegateUserId().toString()); taskService.delegateTask(taskId, reqVO.getDelegateUserId().toString());
// 补充说明委托不单独设置状态如果需要可通过 Task DelegationState 字段判断是否为 DelegationState.PENDING 委托中 // 补充说明委托不单独设置状态如果需要可通过 Task DelegationState 字段判断是否为 DelegationState.PENDING 委托中
LocalDateTime startTime = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().minusSeconds(1);
LocalDateTime endTime = LocalDateTime.now();
Duration duration = Duration.between(startTime, endTime);
long seconds = duration.getSeconds();
//同步更新到流转记录库
taskExtendRecordService.toCreateTaskExtendRecord(
task.getId(),
task.getName()+"("+currentUser.getNickname()+"委托)",
startTime,
endTime,
String.valueOf(userId),
reqVO.getReason(),
duration.getSeconds()*1000,
task.getProcessInstanceId(),
2
);
} }
@Override @Override
@DataPermission(enable = false)
public void transferTask(Long userId, BpmTaskTransferReqVO reqVO) { public void transferTask(Long userId, BpmTaskTransferReqVO reqVO) {
String taskId = reqVO.getId(); String taskId = reqVO.getId();
// 1.1 校验任务 // 1.1 校验任务
Task task = validateTask(userId, reqVO.getId()); Task task = validateTask(userId, reqVO.getId());
Date startDate = task.getCreateTime();
if (task.getAssignee().equals(reqVO.getAssigneeUserId().toString())) { // 校验当前审批人和被转派人不是同一人 if (task.getAssignee().equals(reqVO.getAssigneeUserId().toString())) { // 校验当前审批人和被转派人不是同一人
throw exception(TASK_TRANSFER_FAIL_USER_REPEAT); throw exception(TASK_TRANSFER_FAIL_USER_REPEAT);
} }
@ -816,6 +961,24 @@ public class BpmTaskServiceImpl implements BpmTaskService {
// 3.2 执行转派审批人将任务转派给 assigneeUser // 3.2 执行转派审批人将任务转派给 assigneeUser
// 委托 delegate和转派transfer的差别就在这块的调用 // 委托 delegate和转派transfer的差别就在这块的调用
taskService.setAssignee(taskId, reqVO.getAssigneeUserId().toString()); taskService.setAssignee(taskId, reqVO.getAssigneeUserId().toString());
LocalDateTime startTime = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().minusSeconds(1);
LocalDateTime endTime = LocalDateTime.now();
Duration duration = Duration.between(startTime, endTime);
long seconds = duration.getSeconds();
//同步更新到流转记录库
taskExtendRecordService.toCreateTaskExtendRecord(
task.getId(),
task.getName()+"("+currentUser.getNickname()+"转办)",
startTime,
endTime,
String.valueOf(userId),
reqVO.getReason(),
duration.getSeconds()*1000,
task.getProcessInstanceId(),
2
);
} }
@Override @Override
@ -1300,6 +1463,16 @@ public class BpmTaskServiceImpl implements BpmTaskService {
}); });
}); });
// 扩展属性
userTask.getExtensionElements().forEach((key, value) -> {
//System.out.println("Extension Key: " + key);
if ( key.equals( itemStr ) ) {
value.forEach(extensionElement -> {
//System.out.println("Extension Value: " + extensionElement.getElementText());
valueStrRef.set( extensionElement.getElementText() );
});
}
});
} }
} else { } else {
return ""; return "";

View File

@ -0,0 +1,58 @@
package cn.iocoder.yudao.module.bpm.service.taskextendrecord;
import java.time.LocalDateTime;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.bpm.controller.admin.taskextendrecord.vo.*;
import cn.iocoder.yudao.module.bpm.dal.dataobject.taskextendrecord.TaskExtendRecordDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
/**
* BPM 流转记录扩展 Service 接口
*
* @author 君风
*/
public interface TaskExtendRecordService {
/**
* 创建BPM 流转记录扩展
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createTaskExtendRecord(@Valid TaskExtendRecordSaveReqVO createReqVO);
void toCreateTaskExtendRecord(String taskId, String taskName, LocalDateTime startTime, LocalDateTime endTime, String userId, String reason, Long duration, String processInstanceId, Integer status) ;
/**
* 更新BPM 流转记录扩展
*
* @param updateReqVO 更新信息
*/
void updateTaskExtendRecord(@Valid TaskExtendRecordSaveReqVO updateReqVO);
/**
* 删除BPM 流转记录扩展
*
* @param id 编号
*/
void deleteTaskExtendRecord(Long id);
/**
* 获得BPM 流转记录扩展
*
* @param id 编号
* @return BPM 流转记录扩展
*/
TaskExtendRecordDO getTaskExtendRecord(Long id);
/**
* 获得BPM 流转记录扩展分页
*
* @param pageReqVO 分页查询
* @return BPM 流转记录扩展分页
*/
PageResult<TaskExtendRecordDO> getTaskExtendRecordPage(TaskExtendRecordPageReqVO pageReqVO);
public List<TaskExtendRecordDO> getTaskExtendRecordsByProcessInstanceId(String taskId);
}

View File

@ -0,0 +1,93 @@
package cn.iocoder.yudao.module.bpm.service.taskextendrecord;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.*;
import cn.iocoder.yudao.module.bpm.controller.admin.taskextendrecord.vo.*;
import cn.iocoder.yudao.module.bpm.dal.dataobject.taskextendrecord.TaskExtendRecordDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.dal.mysql.taskextendrecord.TaskExtendRecordMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
/**
* BPM 流转记录扩展 Service 实现类
*
* @author 君风
*/
@Service
@Validated
public class TaskExtendRecordServiceImpl implements TaskExtendRecordService {
@Resource
private TaskExtendRecordMapper taskExtendRecordMapper;
@Override
public Long createTaskExtendRecord(TaskExtendRecordSaveReqVO createReqVO) {
// 插入
TaskExtendRecordDO taskExtendRecord = BeanUtils.toBean(createReqVO, TaskExtendRecordDO.class);
taskExtendRecordMapper.insert(taskExtendRecord);
// 返回
return taskExtendRecord.getId();
}
@Override
public void toCreateTaskExtendRecord(String taskId, String taskName, LocalDateTime startTime,LocalDateTime endTime,String userId,String reason,Long duration,String processInstanceId,Integer status) {
// 插入
TaskExtendRecordDO taskExtendRecord = new TaskExtendRecordDO();
taskExtendRecord.setTaskId(taskId);
taskExtendRecord.setTaskName(taskName);
taskExtendRecord.setStartTime( startTime );
taskExtendRecord.setEndTime( endTime );
taskExtendRecord.setUserId( userId );
taskExtendRecord.setReason( reason );
taskExtendRecord.setDuration( duration );
taskExtendRecord.setProcessInstanceId( processInstanceId );
taskExtendRecord.setStatus( status );
taskExtendRecordMapper.insert(taskExtendRecord);
}
@Override
public void updateTaskExtendRecord(TaskExtendRecordSaveReqVO updateReqVO) {
// 校验存在
validateTaskExtendRecordExists(updateReqVO.getId());
// 更新
TaskExtendRecordDO updateObj = BeanUtils.toBean(updateReqVO, TaskExtendRecordDO.class);
taskExtendRecordMapper.updateById(updateObj);
}
@Override
public void deleteTaskExtendRecord(Long id) {
// 校验存在
validateTaskExtendRecordExists(id);
// 删除
taskExtendRecordMapper.deleteById(id);
}
private void validateTaskExtendRecordExists(Long id) {
if (taskExtendRecordMapper.selectById(id) == null) {
throw exception(TASK_EXTEND_RECORD_NOT_EXISTS);
}
}
@Override
public TaskExtendRecordDO getTaskExtendRecord(Long id) {
return taskExtendRecordMapper.selectById(id);
}
@Override
public PageResult<TaskExtendRecordDO> getTaskExtendRecordPage(TaskExtendRecordPageReqVO pageReqVO) {
return taskExtendRecordMapper.selectPage(pageReqVO);
}
@Override
public List<TaskExtendRecordDO> getTaskExtendRecordsByProcessInstanceId(String taskId) {
return taskExtendRecordMapper.getRecordsByProcessInstanceId(taskId);
}
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.bpm.service.taskextendrecord;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class TaskTransitionLog {
private String id; //任务id
private String name; //任务名称
private String actionType; // 起草转办委托
private String userId; // 执行该操作的用户
private String userName; //用户姓名
private LocalDateTime createTime; //开始时间
private LocalDateTime endTime; //结束时间
private String reason; // 操作意见
private String FormKey;
private long durationInMillis; // 操作意见
private int status;
}

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.home.framework.datapermission.config;
import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer; import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer;
import cn.iocoder.yudao.module.home.dal.dataobject.bgyp.BgypDO; import cn.iocoder.yudao.module.home.dal.dataobject.bgyp.BgypDO;
import cn.iocoder.yudao.module.home.dal.dataobject.clgl.ClglDO; import cn.iocoder.yudao.module.home.dal.dataobject.clgl.ClglDO;
import cn.iocoder.yudao.module.home.dal.dataobject.fwgl.FwglDO;
import cn.iocoder.yudao.module.home.dal.dataobject.hygl.HyglDO; import cn.iocoder.yudao.module.home.dal.dataobject.hygl.HyglDO;
import cn.iocoder.yudao.module.home.dal.dataobject.jbgl.JbglDO; import cn.iocoder.yudao.module.home.dal.dataobject.jbgl.JbglDO;
import cn.iocoder.yudao.module.home.dal.dataobject.kqgl.KqglDO; import cn.iocoder.yudao.module.home.dal.dataobject.kqgl.KqglDO;
@ -30,10 +31,12 @@ public class homeDataPermissionConfiguration {
rule.addDeptColumn(JbglDO.class, "dept_id"); //加班管理 rule.addDeptColumn(JbglDO.class, "dept_id"); //加班管理
rule.addDeptColumn(KqglDO.class, "dept_id"); //考勤管理 rule.addDeptColumn(KqglDO.class, "dept_id"); //考勤管理
rule.addDeptColumn(XjglDO.class, "dept_id"); //销假管理 rule.addDeptColumn(XjglDO.class, "dept_id"); //销假管理
rule.addDeptColumn(FwglDO.class, "dept_id"); //发文管理
// rule.addDeptColumn(DeptDO.class, "id"); // rule.addDeptColumn(DeptDO.class, "id");
// user // user
// AdminUserDO 是想要使用权限的表 id 是对那个字段生效 比如 这个表 user_id 使用户id 那就使用 user_id // AdminUserDO 是想要使用权限的表 id 是对那个字段生效 比如 这个表 user_id 使用户id 那就使用 user_id
rule.addUserColumn(QjglDO.class, "user_id"); rule.addUserColumn(QjglDO.class, "user_id");
rule.addUserColumn(FwglDO.class, "user_id");
}; };
} }
} }

View File

@ -1,10 +1,12 @@
package cn.iocoder.yudao.module.home.service.fwgl; package cn.iocoder.yudao.module.home.service.fwgl;
import cn.iocoder.yudao.module.bpm.service.taskextendrecord.TaskExtendRecordService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import cn.iocoder.yudao.module.home.controller.admin.fwgl.vo.*; import cn.iocoder.yudao.module.home.controller.admin.fwgl.vo.*;
import cn.iocoder.yudao.module.home.dal.dataobject.fwgl.FwglDO; import cn.iocoder.yudao.module.home.dal.dataobject.fwgl.FwglDO;
@ -42,6 +44,9 @@ public class FwglServiceImpl implements FwglService {
@Resource @Resource
private FwglMapper fwglMapper; private FwglMapper fwglMapper;
@Resource
private TaskExtendRecordService taskExtendRecordService;
@Override @Override
public Long saveDraft(Long userId,FwglSaveReqVO createReqVO) { public Long saveDraft(Long userId,FwglSaveReqVO createReqVO) {
// 插入 // 插入
@ -71,6 +76,7 @@ public class FwglServiceImpl implements FwglService {
.setVariables(processInstanceVariables).setBusinessKey(String.valueOf(fwgl.getId())) .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(fwgl.getId()))
.setStartUserSelectAssignees(createReqVO.getStartUserSelectAssignees())); .setStartUserSelectAssignees(createReqVO.getStartUserSelectAssignees()));
// 将工作流的编号更新到 OA 请假单中 // 将工作流的编号更新到 OA 请假单中
fwglMapper.updateById(new FwglDO().setId(fwgl.getId()).setProcessInstanceId(processInstanceId)); fwglMapper.updateById(new FwglDO().setId(fwgl.getId()).setProcessInstanceId(processInstanceId));
//同步更新流程待办库 //同步更新流程待办库
@ -80,6 +86,19 @@ public class FwglServiceImpl implements FwglService {
processInstanceId, processInstanceId,
createReqVO.getCurfullpath() createReqVO.getCurfullpath()
); );
//同步更新到流转记录库
// taskExtendRecordService.toCreateTaskExtendRecord(
// processInstanceId,
// "起草",
// LocalDateTime.now().minusSeconds(20),
// LocalDateTime.now().minusSeconds(20),
// String.valueOf(userId),
// "",
// 0L,
// processInstanceId,
// 2
// );
// 返回 // 返回
return fwgl.getId(); return fwgl.getId();
} }

View File

@ -65,6 +65,7 @@ public class QjglServiceImpl implements QjglService {
// 发起 BPM 流程 // 发起 BPM 流程
Map<String, Object> processInstanceVariables = new HashMap<>(); Map<String, Object> processInstanceVariables = new HashMap<>();
processInstanceVariables.put("day", createReqVO.getDay() );
processInstanceId = processInstanceApi.createProcessInstance(userId, processInstanceId = processInstanceApi.createProcessInstance(userId,
new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY) new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
.setVariables(processInstanceVariables).setBusinessKey(String.valueOf(qjgl.getId())) .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(qjgl.getId()))

View File

@ -230,21 +230,7 @@ const updateForm = async () => {
} }
} }
defineExpose({updateForm}) defineExpose({updateForm})
/** 重置表单 */
const resetForm = () => {
formData.value = {
#foreach ($column in $columns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
}
formRef.value?.resetFields()
}
## 特殊:树表专属逻辑 ## 特殊:树表专属逻辑
#if ( $table.templateType == 2 ) #if ( $table.templateType == 2 )

View File

@ -45,10 +45,11 @@ public interface DeptApi {
* @param ids 部门编号数组 * @param ids 部门编号数组
* @return 部门 Map * @return 部门 Map
*/ */
default Map<Long, DeptRespDTO> getDeptMap(Collection<Long> ids) { Map<Long, DeptRespDTO> getDeptMap(Collection<Long> ids);
List<DeptRespDTO> list = getDeptList(ids); // default Map<Long, DeptRespDTO> getDeptMap(Collection<Long> ids) {
return CollectionUtils.convertMap(list, DeptRespDTO::getId); // List<DeptRespDTO> list = getDeptList(ids);
} // return CollectionUtils.convertMap(list, DeptRespDTO::getId);
// }
/** /**
* 获得指定部门的所有子部门 * 获得指定部门的所有子部门

View File

@ -61,10 +61,11 @@ public interface AdminUserApi {
* @param ids 用户编号数组 * @param ids 用户编号数组
* @return 用户 Map * @return 用户 Map
*/ */
default Map<Long, AdminUserRespDTO> getUserMap(Collection<Long> ids) { Map<Long, AdminUserRespDTO> getUserMap(Collection<Long> ids);
List<AdminUserRespDTO> users = getUserList(ids); // default Map<Long, AdminUserRespDTO> getUserMap(Collection<Long> ids) {
return CollectionUtils.convertMap(users, AdminUserRespDTO::getId); // List<AdminUserRespDTO> users = getUserList(ids);
} // return CollectionUtils.convertMap(users, AdminUserRespDTO::getId);
// }
/** /**
* 校验用户是否有效如下情况视为无效 * 校验用户是否有效如下情况视为无效

View File

@ -1,6 +1,8 @@
package cn.iocoder.yudao.module.system.api.dept; package cn.iocoder.yudao.module.system.api.dept;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
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.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.service.dept.DeptService; import cn.iocoder.yudao.module.system.service.dept.DeptService;
@ -10,6 +12,7 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 部门 API 实现类 * 部门 API 实现类
@ -38,7 +41,12 @@ public class DeptApiImpl implements DeptApi {
public void validateDeptList(Collection<Long> ids) { public void validateDeptList(Collection<Long> ids) {
deptService.validateDeptList(ids); deptService.validateDeptList(ids);
} }
@Override
@DataPermission(enable = false)
public Map<Long, DeptRespDTO> getDeptMap(Collection<Long> ids) {
List<DeptRespDTO> list = getDeptList(ids);
return CollectionUtils.convertMap(list, DeptRespDTO::getId);
}
@Override @Override
public List<DeptRespDTO> getChildDeptList(Long id) { public List<DeptRespDTO> getChildDeptList(Long id) {
List<DeptDO> childDeptList = deptService.getChildDeptList(id); List<DeptDO> childDeptList = deptService.getChildDeptList(id);

View File

@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.system.api.user;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
@ -11,10 +13,7 @@ import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@ -36,7 +35,12 @@ public class AdminUserApiImpl implements AdminUserApi {
AdminUserDO user = userService.getUser(id); AdminUserDO user = userService.getUser(id);
return BeanUtils.toBean(user, AdminUserRespDTO.class); return BeanUtils.toBean(user, AdminUserRespDTO.class);
} }
@Override
@DataPermission(enable = false)
public Map<Long, AdminUserRespDTO> getUserMap(Collection<Long> ids) {
List<AdminUserRespDTO> users = getUserList(ids);
return CollectionUtils.convertMap(users, AdminUserRespDTO::getId);
}
@Override @Override
public List<AdminUserRespDTO> getUserListBySubordinate(Long id) { public List<AdminUserRespDTO> getUserListBySubordinate(Long id) {
// 1.1 获取用户负责的部门 // 1.1 获取用户负责的部门

View File

@ -7,7 +7,7 @@ spring:
autoconfigure: autoconfigure:
exclude: exclude:
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
# - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置 想要开启注释或者删除这一行即可 - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置 想要开启注释或者删除这一行即可
- de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置 - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置
- de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置 - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
@ -46,7 +46,7 @@ spring:
primary: master primary: master
datasource: datasource:
master: master:
url: jdbc:mysql://192.168.1.28:3306/yudao-vue?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 url: jdbc:mysql://140.143.164.40:3306/yudao-oa2?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
# url: jdbc:mysql://192.168.1.28:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 # url: jdbc:mysql://192.168.1.28:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
# url: jdbc:mysql://192.168.45.131:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai # MySQL Connector/J 5.X 连接的示例 # url: jdbc:mysql://192.168.45.131:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai # MySQL Connector/J 5.X 连接的示例
# url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例
@ -71,9 +71,9 @@ spring:
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
redis: redis:
host: 192.168.1.28 # 地址140.143.164.40 host: 140.143.164.40 # 地址140.143.164.40
port: 6379 # 端口 port: 6379 # 端口
database: 0 # 数据库索引 database: 10 # 数据库索引
password: 123456 password: 123456
# password: dev # 密码,建议生产环境开启 # password: dev # 密码,建议生产环境开启

View File

@ -57,8 +57,9 @@ flowable:
# 1. false: 默认值Flowable 启动时,对比数据库表中保存的版本,如果不匹配。将抛出异常 # 1. false: 默认值Flowable 启动时,对比数据库表中保存的版本,如果不匹配。将抛出异常
# 2. true: 启动时会对数据库中所有表进行更新操作,如果表存在,不做处理,反之,自动创建表 # 2. true: 启动时会对数据库中所有表进行更新操作,如果表存在,不做处理,反之,自动创建表
# 3. create_drop: 启动时自动创建表,关闭时自动删除表 # 3. create_drop: 启动时自动创建表,关闭时自动删除表
# 4. drop_create: 启动时,删除旧表,再创建新表 # 4. drop_create: 启动时,删除旧表,再创建新表
database-schema-update: true # 设置为 false可通过 https://github.com/flowable/flowable-sql 初始化 database-schema-update: false # 设置为 false可通过 https://github.com/flowable/flowable-sql 初始化
db-history-used: true # flowable6 默认 true 生成信息表,无需手动设置 db-history-used: true # flowable6 默认 true 生成信息表,无需手动设置
check-process-definitions: false # 设置为 false禁用 /resources/processes 自动部署 BPMN XML 流程 check-process-definitions: false # 设置为 false禁用 /resources/processes 自动部署 BPMN XML 流程
history-level: audit # full保存历史数据的最高级别可保存全部流程相关细节包括流程流转各节点参数 history-level: audit # full保存历史数据的最高级别可保存全部流程相关细节包括流程流转各节点参数