From a8a9e2625ee2f24bd5338e762e4f138649e1270e Mon Sep 17 00:00:00 2001 From: dengqichen Date: Tue, 11 Nov 2025 21:49:59 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=83=A8=E7=BD=B2=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TeamEnvironmentConfigServiceImpl.java | 145 ++++++++++++++++-- 1 file changed, 135 insertions(+), 10 deletions(-) diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/TeamEnvironmentConfigServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/TeamEnvironmentConfigServiceImpl.java index 6234500c..20d68bbd 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/TeamEnvironmentConfigServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/TeamEnvironmentConfigServiceImpl.java @@ -102,15 +102,17 @@ public class TeamEnvironmentConfigServiceImpl @Override @Transactional(rollbackFor = Exception.class) public TeamEnvironmentConfigDTO create(TeamEnvironmentConfigDTO dto) { - // 执行兜底逻辑:确保数据一致性 - applyDataConsistencyRules(dto); + // 0) 前置处理:数据归一化和业务规则 + prepareForCreate(dto); - // 创建主配置 + // 1) 创建主配置(会自动调用 validateUniqueConstraints) TeamEnvironmentConfigDTO result = super.create(dto); - // 保存或更新通知配置 + // 2) 保存通知配置(基于 teamId + environmentId) saveOrUpdateNotificationConfig(dto); + // 3) 附带扩展信息(环境名、通知配置含渠道名、应用数量) + attachSnapshot(result); return result; } @@ -120,18 +122,37 @@ public class TeamEnvironmentConfigServiceImpl @Override @Transactional(rollbackFor = Exception.class) public TeamEnvironmentConfigDTO update(Long id, TeamEnvironmentConfigDTO dto) { - // 执行兜底逻辑:确保数据一致性 - applyDataConsistencyRules(dto); + // 0) 前置处理:数据归一化、业务规则和维度验证 + prepareForUpdate(id, dto); - // 更新主配置 + // 1) 更新主配置(会自动调用 validateUniqueConstraints) TeamEnvironmentConfigDTO result = super.update(id, dto); - // 保存或更新通知配置 + // 2) 保存通知配置 saveOrUpdateNotificationConfig(dto); + // 3) 附带扩展信息(环境名、通知配置含渠道名、应用数量) + attachSnapshot(result); return result; } + /** + * 校验唯一性约束 + * + * @param dto 团队环境配置DTO + */ + @Override + protected void validateUniqueConstraints(TeamEnvironmentConfigDTO dto) { + if (dto == null || dto.getTeamId() == null || dto.getEnvironmentId() == null) { + return; + } + + // 检查 teamId + environmentId 组合唯一性 + if (teamEnvironmentConfigRepository.existsByTeamIdAndEnvironmentId(dto.getTeamId(), dto.getEnvironmentId())) { + throw new BusinessException(ResponseCode.CONFLICT, new Object[]{"团队/环境配置已存在"}); + } + } + /** * 数据一致性兜底逻辑 *

规则: @@ -294,7 +315,7 @@ public class TeamEnvironmentConfigServiceImpl } /** - * 重写删除方法,删除前校验该团队环境下是否有绑定的应用 + * 重写删除方法,删除前校验该团队环境下是否有绑定的应用,并级联删除通知配置 * * @param id 团队环境配置ID */ @@ -317,10 +338,114 @@ public class TeamEnvironmentConfigServiceImpl throw new BusinessException(ResponseCode.TEAM_ENVIRONMENT_HAS_APPLICATIONS, new Object[] {appCount}); } - // 3. 执行删除(逻辑删除) + //3. 删除关联的通知配置 + Optional notificationConfig = + teamEnvironmentNotificationConfigRepository.findByTeamIdAndEnvironmentId( + config.getTeamId(), + config.getEnvironmentId() + ); + + if (notificationConfig.isPresent()) { + teamEnvironmentNotificationConfigRepository.deleteById(notificationConfig.get().getId()); + log.info("删除关联的通知配置: teamId={}, environmentId={}", + config.getTeamId(), config.getEnvironmentId()); + } + + // 4. 执行删除(逻辑删除) super.delete(id); log.info("成功删除团队环境配置: id={}, teamId={}, environmentId={}", id, config.getTeamId(), config.getEnvironmentId()); } + +/** + * 创建前预处理 + * 包含数据归一化和业务规则应用 + */ + private void prepareForCreate(TeamEnvironmentConfigDTO dto) { + if (dto == null) { + return; + } + + // 1) 应用业务规则 + applyDataConsistencyRules(dto); + + // 2) 数据归一化 + normalizeDataFields(dto); + } + + /** + * 更新前预处理 + * 包含数据归一化、业务规则应用和维度验证 + */ + private void prepareForUpdate(Long id, TeamEnvironmentConfigDTO dto) { + if (dto == null) { + return; + } + + // 1) 验证维度不可变更 + validateDimensionChangeOnUpdate(id, dto); + + // 2) 应用业务规则 + applyDataConsistencyRules(dto); + + // 3) 数据归一化 + normalizeDataFields(dto); + } + + /** + * 数据字段归一化 + * 处理空值、格式标准化等 + */ + private void normalizeDataFields(TeamEnvironmentConfigDTO dto) { + if (dto == null) { + return; + } + + // 空集合归一化 + if (dto.getApproverUserIds() != null && dto.getApproverUserIds().isEmpty()) { + dto.setApproverUserIds(null); + } + + // 归一化通知配置的 team/environment(以主 DTO 为准) + if (dto.getNotificationConfig() != null) { + TeamEnvironmentNotificationConfigDTO nc = dto.getNotificationConfig(); + nc.setTeamId(dto.getTeamId()); + nc.setEnvironmentId(dto.getEnvironmentId()); + } + } + + /** + * 验证更新时维度不可变更 + */ + private void validateDimensionChangeOnUpdate(Long id, TeamEnvironmentConfigDTO dto) { + TeamEnvironmentConfig origin = teamEnvironmentConfigRepository.findById(id) + .orElseThrow(() -> new BusinessException(ResponseCode.TEAM_CONFIG_NOT_FOUND, new Object[] {id})); + + // 禁止修改 teamId 和 environmentId + if (dto.getTeamId() != null && !Objects.equals(dto.getTeamId(), origin.getTeamId())) { + throw new BusinessException(ResponseCode.CONFLICT, new Object[]{"不允许变更 teamId"}); + } + if (dto.getEnvironmentId() != null && !Objects.equals(dto.getEnvironmentId(), origin.getEnvironmentId())) { + throw new BusinessException(ResponseCode.CONFLICT, new Object[]{"不允许变更 environmentId"}); + } + + // 将主维度补齐,确保后续处理使用 + dto.setTeamId(origin.getTeamId()); + dto.setEnvironmentId(origin.getEnvironmentId()); + } + + + /** + * 在返回结果上附带扩展数据快照(环境名、通知配置含渠道名、应用数量) + */ + private void attachSnapshot(TeamEnvironmentConfigDTO result) { + if (result == null) { + return; + } + // 复用已有批量填充逻辑(单元素列表) + List list = new ArrayList<>(); + list.add(result); + fillExtendedFields(list); + } }