增加构建通知
This commit is contained in:
parent
c09d82e7b5
commit
88f5ec1d5c
@ -8,7 +8,7 @@ import java.time.LocalDateTime;
|
||||
/**
|
||||
* 部署审批任务DTO
|
||||
*
|
||||
* <p>扩展了审批任务的基本信息,增加部署相关的业务上下文
|
||||
* <p>结构化的审批任务信息,包含审批任务、部署记录、关联实体等信息
|
||||
* <p>用于部署审批列表,让审批人员快速了解审批内容
|
||||
*
|
||||
* @author qqchen
|
||||
@ -18,7 +18,35 @@ import java.time.LocalDateTime;
|
||||
@Schema(description = "部署审批任务信息")
|
||||
public class DeployApprovalTaskDTO {
|
||||
|
||||
// ============ 审批任务基本信息 ============
|
||||
// ========== 审批任务信息 ==========
|
||||
@Schema(description = "审批任务信息")
|
||||
private ApprovalTaskInfo approvalTask;
|
||||
|
||||
// ========== 部署记录信息 ==========
|
||||
@Schema(description = "部署记录信息")
|
||||
private DeployRecordInfo deployRecord;
|
||||
|
||||
// ========== 关联实体信息 ==========
|
||||
@Schema(description = "团队信息")
|
||||
private TeamInfo team;
|
||||
|
||||
@Schema(description = "应用信息")
|
||||
private ApplicationInfo application;
|
||||
|
||||
@Schema(description = "环境信息")
|
||||
private EnvironmentInfo environment;
|
||||
|
||||
@Schema(description = "发起人信息")
|
||||
private UserSimpleInfo deployUser;
|
||||
|
||||
// ========== 嵌套类定义 ==========
|
||||
|
||||
/**
|
||||
* 审批任务信息
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "审批任务信息")
|
||||
public static class ApprovalTaskInfo {
|
||||
|
||||
@Schema(description = "任务ID")
|
||||
private String taskId;
|
||||
@ -35,7 +63,7 @@ public class DeployApprovalTaskDTO {
|
||||
@Schema(description = "流程定义ID")
|
||||
private String processDefinitionId;
|
||||
|
||||
@Schema(description = "审批人")
|
||||
@Schema(description = "审批人用户名")
|
||||
private String assignee;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@ -44,6 +72,9 @@ public class DeployApprovalTaskDTO {
|
||||
@Schema(description = "到期时间")
|
||||
private LocalDateTime dueDate;
|
||||
|
||||
@Schema(description = "待审批时长(毫秒)- 从任务创建到现在的时长")
|
||||
private Long pendingDuration;
|
||||
|
||||
@Schema(description = "审批标题")
|
||||
private String approvalTitle;
|
||||
|
||||
@ -61,49 +92,97 @@ public class DeployApprovalTaskDTO {
|
||||
|
||||
@Schema(description = "是否必须填写意见")
|
||||
private Boolean requireComment;
|
||||
}
|
||||
|
||||
// ============ 部署业务上下文信息 ============
|
||||
/**
|
||||
* 部署记录信息
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "部署记录信息")
|
||||
public static class DeployRecordInfo {
|
||||
|
||||
@Schema(description = "部署记录ID")
|
||||
private Long deployRecordId;
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "业务标识(UUID)")
|
||||
private String businessKey;
|
||||
|
||||
@Schema(description = "团队ID")
|
||||
private Long teamId;
|
||||
|
||||
@Schema(description = "团队名称")
|
||||
private String teamName;
|
||||
|
||||
@Schema(description = "应用ID")
|
||||
private Long applicationId;
|
||||
|
||||
@Schema(description = "应用编码")
|
||||
private String applicationCode;
|
||||
|
||||
@Schema(description = "应用名称")
|
||||
private String applicationName;
|
||||
|
||||
@Schema(description = "环境ID")
|
||||
private Long environmentId;
|
||||
|
||||
@Schema(description = "环境编码")
|
||||
private String environmentCode;
|
||||
|
||||
@Schema(description = "环境名称")
|
||||
private String environmentName;
|
||||
|
||||
@Schema(description = "发起人")
|
||||
private String deployBy;
|
||||
|
||||
@Schema(description = "部署备注")
|
||||
private String deployRemark;
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "部署开始时间")
|
||||
private LocalDateTime deployStartTime;
|
||||
private LocalDateTime startTime;
|
||||
}
|
||||
|
||||
@Schema(description = "待审批时长(毫秒)- 从任务创建到现在的时长")
|
||||
private Long pendingDuration;
|
||||
/**
|
||||
* 团队信息
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "团队信息")
|
||||
public static class TeamInfo {
|
||||
|
||||
@Schema(description = "团队ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "团队名称")
|
||||
private String name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用信息
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "应用信息")
|
||||
public static class ApplicationInfo {
|
||||
|
||||
@Schema(description = "应用ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "应用编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "应用名称")
|
||||
private String name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 环境信息
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "环境信息")
|
||||
public static class EnvironmentInfo {
|
||||
|
||||
@Schema(description = "环境ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "环境编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "环境名称")
|
||||
private String name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户简要信息
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "用户简要信息")
|
||||
public static class UserSimpleInfo {
|
||||
|
||||
@Schema(description = "用户名")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "昵称")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "邮箱")
|
||||
private String email;
|
||||
|
||||
@Schema(description = "手机号")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "部门名称")
|
||||
private String departmentName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -72,6 +72,8 @@ public class DeployExecuteRequest {
|
||||
@Schema(description = "部署备注")
|
||||
private String deployRemark;
|
||||
|
||||
private String deployUser;
|
||||
|
||||
/**
|
||||
* Jenkins配置
|
||||
*/
|
||||
|
||||
@ -755,9 +755,7 @@ public class DeployServiceImpl implements IDeployService {
|
||||
* 创建部署记录
|
||||
*/
|
||||
private void createDeployRecord(DeployExecuteRequest request, WorkflowInstanceDTO workflowInstance, String businessKey) {
|
||||
String currentUsername = SecurityUtils.getCurrentUsername();
|
||||
deployRecordService.createDeployRecord(workflowInstance.getId(), businessKey, request.getTeamApplicationId(), request.getTeamId(), request.getApplicationId(), request.getEnvironmentId(), currentUsername, request.getDeployRemark());
|
||||
|
||||
deployRecordService.createDeployRecord(workflowInstance.getId(), businessKey, request.getTeamApplicationId(), request.getTeamId(), request.getApplicationId(), request.getEnvironmentId(), request.getDeployUser(), request.getDeployRemark());
|
||||
log.info("部署记录已创建: businessKey={}, workflowInstanceId={}", businessKey, workflowInstance.getId());
|
||||
}
|
||||
|
||||
@ -820,20 +818,21 @@ public class DeployServiceImpl implements IDeployService {
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 批量查询团队信息(解决 N+1 查询问题)
|
||||
// 4. 批量查询团队信息和用户信息(解决 N+1 查询问题)
|
||||
enrichTeamInfo(result);
|
||||
enrichDeployUserInfo(result);
|
||||
|
||||
// 5. 后置筛选:按团队和环境过滤
|
||||
if (teamId != null) {
|
||||
result = result.stream()
|
||||
.filter(task -> teamId.equals(task.getTeamId()))
|
||||
.filter(task -> task.getTeam() != null && teamId.equals(task.getTeam().getId()))
|
||||
.collect(Collectors.toList());
|
||||
log.debug("按团队ID筛选后剩余 {} 个任务", result.size());
|
||||
}
|
||||
|
||||
if (environmentId != null) {
|
||||
result = result.stream()
|
||||
.filter(task -> environmentId.equals(task.getEnvironmentId()))
|
||||
.filter(task -> task.getEnvironment() != null && environmentId.equals(task.getEnvironment().getId()))
|
||||
.collect(Collectors.toList());
|
||||
log.debug("按环境ID筛选后剩余 {} 个任务", result.size());
|
||||
}
|
||||
@ -879,56 +878,79 @@ public class DeployServiceImpl implements IDeployService {
|
||||
// 5. 构建 DTO
|
||||
DeployApprovalTaskDTO dto = new DeployApprovalTaskDTO();
|
||||
|
||||
// 5.1 审批任务基本信息
|
||||
dto.setTaskId(task.getId());
|
||||
dto.setTaskName(task.getName());
|
||||
dto.setTaskDescription(task.getDescription());
|
||||
dto.setProcessInstanceId(task.getProcessInstanceId());
|
||||
dto.setProcessDefinitionId(task.getProcessDefinitionId());
|
||||
dto.setAssignee(task.getAssignee());
|
||||
// 5.1 构建审批任务信息
|
||||
DeployApprovalTaskDTO.ApprovalTaskInfo approvalTask = new DeployApprovalTaskDTO.ApprovalTaskInfo();
|
||||
approvalTask.setTaskId(task.getId());
|
||||
approvalTask.setTaskName(task.getName());
|
||||
approvalTask.setTaskDescription(task.getDescription());
|
||||
approvalTask.setProcessInstanceId(task.getProcessInstanceId());
|
||||
approvalTask.setProcessDefinitionId(task.getProcessDefinitionId());
|
||||
approvalTask.setAssignee(task.getAssignee());
|
||||
|
||||
if (task.getCreateTime() != null) {
|
||||
dto.setCreateTime(LocalDateTime.ofInstant(
|
||||
LocalDateTime createTime = LocalDateTime.ofInstant(
|
||||
task.getCreateTime().toInstant(),
|
||||
ZoneId.systemDefault()));
|
||||
ZoneId.systemDefault());
|
||||
approvalTask.setCreateTime(createTime);
|
||||
|
||||
// 计算待审批时长
|
||||
long pendingMillis = Duration.between(createTime, LocalDateTime.now()).toMillis();
|
||||
approvalTask.setPendingDuration(pendingMillis);
|
||||
}
|
||||
|
||||
if (task.getDueDate() != null) {
|
||||
dto.setDueDate(LocalDateTime.ofInstant(
|
||||
approvalTask.setDueDate(LocalDateTime.ofInstant(
|
||||
task.getDueDate().toInstant(),
|
||||
ZoneId.systemDefault()));
|
||||
}
|
||||
|
||||
// 5.2 审批配置信息(从审批节点的 NodeContext 中获取 ApprovalInputMapping)
|
||||
// 5.2 填充审批配置信息(从审批节点的 NodeContext 中获取 ApprovalInputMapping)
|
||||
String nodeId = task.getTaskDefinitionKey();
|
||||
ApprovalInputMapping approvalInputs = extractApprovalInputMapping(variables, nodeId);
|
||||
if (approvalInputs != null) {
|
||||
dto.setApprovalTitle(approvalInputs.getApprovalTitle());
|
||||
dto.setApprovalContent(approvalInputs.getApprovalContent());
|
||||
dto.setApprovalMode(approvalInputs.getApprovalMode() != null
|
||||
approvalTask.setApprovalTitle(approvalInputs.getApprovalTitle());
|
||||
approvalTask.setApprovalContent(approvalInputs.getApprovalContent());
|
||||
approvalTask.setApprovalMode(approvalInputs.getApprovalMode() != null
|
||||
? approvalInputs.getApprovalMode().name()
|
||||
: null);
|
||||
dto.setAllowDelegate(approvalInputs.getAllowDelegate());
|
||||
dto.setAllowAddSign(approvalInputs.getAllowAddSign());
|
||||
dto.setRequireComment(approvalInputs.getRequireComment());
|
||||
approvalTask.setAllowDelegate(approvalInputs.getAllowDelegate());
|
||||
approvalTask.setAllowAddSign(approvalInputs.getAllowAddSign());
|
||||
approvalTask.setRequireComment(approvalInputs.getRequireComment());
|
||||
}
|
||||
dto.setApprovalTask(approvalTask);
|
||||
|
||||
// 5.3 部署业务上下文信息(从 variables 还原 DeployExecuteRequest)
|
||||
// 5.3 构建部署记录信息
|
||||
DeployApprovalTaskDTO.DeployRecordInfo deployRecordInfo = new DeployApprovalTaskDTO.DeployRecordInfo();
|
||||
deployRecordInfo.setId(deployRecord.getId());
|
||||
deployRecordInfo.setBusinessKey(businessKey);
|
||||
deployRecordInfo.setRemark(deployRecord.getDeployRemark());
|
||||
deployRecordInfo.setStartTime(deployRecord.getStartTime());
|
||||
dto.setDeployRecord(deployRecordInfo);
|
||||
|
||||
// 5.4 构建关联实体信息(从 variables 还原 DeployExecuteRequest)
|
||||
DeployExecuteRequest deployRequest = JsonUtils.fromMap(variables, DeployExecuteRequest.class);
|
||||
dto.setDeployRecordId(deployRecord.getId());
|
||||
dto.setBusinessKey(businessKey);
|
||||
dto.setDeployStartTime(deployRecord.getStartTime());
|
||||
|
||||
// 使用 BeanUtils 批量复制同名字段
|
||||
BeanUtils.copyProperties(deployRequest, dto);
|
||||
// 团队信息
|
||||
DeployApprovalTaskDTO.TeamInfo team = new DeployApprovalTaskDTO.TeamInfo();
|
||||
team.setId(deployRequest.getTeamId());
|
||||
// 团队名称通过批量查询填充(见 enrichTeamInfo 方法)
|
||||
dto.setTeam(team);
|
||||
|
||||
// 5.4 计算待审批时长(团队名称通过批量查询填充)
|
||||
if (dto.getCreateTime() != null) {
|
||||
long pendingMillis = Duration.between(dto.getCreateTime(), LocalDateTime.now()).toMillis();
|
||||
dto.setPendingDuration(pendingMillis);
|
||||
}
|
||||
// 应用信息
|
||||
DeployApprovalTaskDTO.ApplicationInfo application = new DeployApprovalTaskDTO.ApplicationInfo();
|
||||
application.setId(deployRequest.getApplicationId());
|
||||
application.setCode(deployRequest.getApplicationCode());
|
||||
application.setName(deployRequest.getApplicationName());
|
||||
dto.setApplication(application);
|
||||
|
||||
// 5.6 自动解析 EL 表达式(如 ${deploy.applicationName})
|
||||
// 环境信息
|
||||
DeployApprovalTaskDTO.EnvironmentInfo environment = new DeployApprovalTaskDTO.EnvironmentInfo();
|
||||
environment.setId(deployRequest.getEnvironmentId());
|
||||
environment.setCode(deployRequest.getEnvironmentCode());
|
||||
environment.setName(deployRequest.getEnvironmentName());
|
||||
dto.setEnvironment(environment);
|
||||
|
||||
// 5.5 自动解析 EL 表达式(如 ${deploy.applicationName})
|
||||
SpelExpressionResolver.resolveObject(dto, variables);
|
||||
|
||||
return dto;
|
||||
@ -1017,6 +1039,11 @@ public class DeployServiceImpl implements IDeployService {
|
||||
*
|
||||
* @param dtoList 待填充的 DTO 列表
|
||||
*/
|
||||
/**
|
||||
* 批量查询并填充团队信息
|
||||
*
|
||||
* @param dtoList 待填充的 DTO 列表
|
||||
*/
|
||||
private void enrichTeamInfo(List<DeployApprovalTaskDTO> dtoList) {
|
||||
if (dtoList == null || dtoList.isEmpty()) {
|
||||
return;
|
||||
@ -1024,7 +1051,9 @@ public class DeployServiceImpl implements IDeployService {
|
||||
|
||||
// 1. 收集所有 teamIds
|
||||
Set<Long> teamIds = dtoList.stream()
|
||||
.map(DeployApprovalTaskDTO::getTeamId)
|
||||
.map(DeployApprovalTaskDTO::getTeam)
|
||||
.filter(Objects::nonNull)
|
||||
.map(DeployApprovalTaskDTO.TeamInfo::getId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
@ -1038,16 +1067,75 @@ public class DeployServiceImpl implements IDeployService {
|
||||
|
||||
// 3. 填充团队名称
|
||||
for (DeployApprovalTaskDTO dto : dtoList) {
|
||||
Long teamId = dto.getTeamId();
|
||||
if (teamId != null) {
|
||||
Team team = teamMap.get(teamId);
|
||||
if (dto.getTeam() != null && dto.getTeam().getId() != null) {
|
||||
Team team = teamMap.get(dto.getTeam().getId());
|
||||
if (team != null) {
|
||||
dto.setTeamName(team.getTeamName());
|
||||
dto.getTeam().setName(team.getTeamName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量查询并填充部署发起人信息
|
||||
*
|
||||
* @param dtoList 待填充的 DTO 列表
|
||||
*/
|
||||
private void enrichDeployUserInfo(List<DeployApprovalTaskDTO> dtoList) {
|
||||
if (dtoList == null || dtoList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 收集所有 deployBy 用户名
|
||||
Set<String> usernames = dtoList.stream()
|
||||
.map(DeployApprovalTaskDTO::getDeployRecord)
|
||||
.filter(Objects::nonNull)
|
||||
.map(record -> {
|
||||
// 从原始 DeployRecord 获取 deployBy(需要通过 deployRecordId 查询)
|
||||
if (record.getId() != null) {
|
||||
return deployRecordRepository.findById(record.getId())
|
||||
.map(DeployRecord::getDeployBy)
|
||||
.orElse(null);
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (usernames.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 批量查询用户信息
|
||||
List<User> users = userRepository.findByUsernameInAndDeletedFalse(usernames);
|
||||
Map<String, User> userMap = users.stream()
|
||||
.collect(Collectors.toMap(User::getUsername, u -> u));
|
||||
|
||||
// 3. 填充用户信息
|
||||
for (DeployApprovalTaskDTO dto : dtoList) {
|
||||
if (dto.getDeployRecord() != null && dto.getDeployRecord().getId() != null) {
|
||||
deployRecordRepository.findById(dto.getDeployRecord().getId())
|
||||
.ifPresent(deployRecord -> {
|
||||
String username = deployRecord.getDeployBy();
|
||||
if (username != null) {
|
||||
User user = userMap.get(username);
|
||||
if (user != null) {
|
||||
DeployApprovalTaskDTO.UserSimpleInfo userInfo = new DeployApprovalTaskDTO.UserSimpleInfo();
|
||||
userInfo.setUsername(user.getUsername());
|
||||
userInfo.setNickname(user.getNickname());
|
||||
userInfo.setEmail(user.getEmail());
|
||||
userInfo.setPhone(user.getPhone());
|
||||
if (user.getDepartment() != null) {
|
||||
userInfo.setDepartmentName(user.getDepartment().getName());
|
||||
}
|
||||
dto.setDeployUser(userInfo);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从流程变量中提取审批节点的 ApprovalInputMapping
|
||||
* <p>从 NodeContext 的 inputs 字段中解析审批配置
|
||||
|
||||
@ -4,6 +4,8 @@ import com.qqchen.deploy.backend.system.entity.User;
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
@ -14,6 +16,11 @@ public interface IUserRepository extends IBaseRepository<User, Long> {
|
||||
*/
|
||||
Optional<User> findByUsernameAndDeletedFalse(String username);
|
||||
|
||||
/**
|
||||
* 批量根据用户名查找未删除的用户(用于批量查询)
|
||||
*/
|
||||
List<User> findByUsernameInAndDeletedFalse(Collection<String> usernames);
|
||||
|
||||
/**
|
||||
* 检查用户名是否存在(包括已删除的记录)
|
||||
*/
|
||||
|
||||
Loading…
Reference in New Issue
Block a user