diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/problemtype/GardenProblemTypeMapper.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/problemtype/GardenProblemTypeMapper.java index 8805a5a..25e0940 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/problemtype/GardenProblemTypeMapper.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/problemtype/GardenProblemTypeMapper.java @@ -6,6 +6,8 @@ import com.zteits.urbanops.framework.mybatis.core.mapper.BaseMapperX; import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypePageReqVO; import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; import java.util.ArrayList; import java.util.List; @@ -63,25 +65,55 @@ public interface GardenProblemTypeMapper extends BaseMapperX() + .eq(GardenProblemTypeDO::getTypeName, typeName) + .eq(GardenProblemTypeDO::getParentCode, parentCode) + .eq(GardenProblemTypeDO::getLevel, level) + .last("LIMIT 1")); + } + + /** + * 绕过逻辑删除,直接查 typeCode 是否物理存在(用于编码生成时避免唯一键冲突) + */ + @Select("SELECT COUNT(1) FROM garden_problem_type WHERE type_code = #{code}") + int countByTypeCodeRaw(@Param("code") String code); + + /** * 生成下一个编码:父级编码 + 5位递增序号 * 如 parentCode=BIZ_GARDEN → BIZ_GARDEN00001, BIZ_GARDEN00002 + * 注意:加 LENGTH 条件避免匹配到子级编码;绕过逻辑删除检查确保唯一键可用 */ default String generateNextCode(String parentCode) { + int expectedLength = parentCode.length() + 5; List list = selectList(new LambdaQueryWrapperX() .likeRight(GardenProblemTypeDO::getTypeCode, parentCode) + .apply("LENGTH(type_code) = {0}", expectedLength) .orderByDesc(GardenProblemTypeDO::getTypeCode) .last("LIMIT 1")); + int seq; if (list == null || list.isEmpty()) { - return parentCode + "00001"; - } - String maxCode = list.get(0).getTypeCode(); - String seqStr = maxCode.substring(parentCode.length()); - try { - int seq = Integer.parseInt(seqStr) + 1; - return parentCode + String.format("%05d", seq); - } catch (NumberFormatException e) { - return parentCode + "00001"; + seq = 1; + } else { + String maxCode = list.get(0).getTypeCode(); + String seqStr = maxCode.substring(parentCode.length()); + try { + seq = Integer.parseInt(seqStr) + 1; + } catch (NumberFormatException e) { + seq = 1; + } } + // 跳过被逻辑删除记录占用的编码 + int maxAttempts = 100; + String nextCode; + do { + nextCode = parentCode + String.format("%05d", seq); + seq++; + } while (countByTypeCodeRaw(nextCode) > 0 && --maxAttempts > 0); + return nextCode; } } diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/ErrorCodeConstants.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/ErrorCodeConstants.java index e03d6ba..a7f3906 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/ErrorCodeConstants.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/ErrorCodeConstants.java @@ -150,6 +150,7 @@ public interface ErrorCodeConstants { // ========== 问题类型配置 1-100-009-000 ========== ErrorCode PROBLEM_TYPE_NOT_EXISTS = new ErrorCode(1100009000, "问题类型不存在"); ErrorCode PROBLEM_TYPE_CODE_EXISTS = new ErrorCode(1100009001, "问题类型编码已存在"); + ErrorCode PROBLEM_TYPE_NAME_DUPLICATE = new ErrorCode(1100009002, "同级下问题类型名称已存在,一级、二级、三级类型名称不能同时重复"); // ========== 一树一档案巡检与风险评估 1-100-008-000 ========== ErrorCode TREE_INSPECTION_NOT_EXISTS = new ErrorCode(1100008001, "巡检评估记录不存在"); diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/problemtype/GardenProblemTypeServiceImpl.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/problemtype/GardenProblemTypeServiceImpl.java index f9edb4c..4cc858e 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/problemtype/GardenProblemTypeServiceImpl.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/problemtype/GardenProblemTypeServiceImpl.java @@ -13,6 +13,7 @@ import jakarta.annotation.Resource; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; @@ -43,6 +44,9 @@ public class GardenProblemTypeServiceImpl implements GardenProblemTypeService { public Long createProblemType(ProblemTypeSaveReqVO createReqVO) { // 校验编码唯一性 validateTypeCodeUnique(createReqVO.getTypeCode(), null); + // 校验名称在同级父节点下唯一 + validateTypeNameUniqueUnderParent(createReqVO.getTypeName(), + createReqVO.getParentCode(), createReqVO.getLevel(), null); // 插入 GardenProblemTypeDO problemType = BeanUtils.toBean(createReqVO, GardenProblemTypeDO.class); gardenProblemTypeMapper.insert(problemType); @@ -81,6 +85,15 @@ public class GardenProblemTypeServiceImpl implements GardenProblemTypeService { } } + private void validateTypeNameUniqueUnderParent(String typeName, String parentCode, + Integer level, Long excludeId) { + GardenProblemTypeDO exist = gardenProblemTypeMapper.selectByNameAndParentAndLevel( + typeName, parentCode, level); + if (exist != null && (excludeId == null || !exist.getId().equals(excludeId))) { + throw exception(PROBLEM_TYPE_NAME_DUPLICATE); + } + } + @Override public GardenProblemTypeDO getProblemType(Long id) { return gardenProblemTypeMapper.selectById(id); @@ -186,6 +199,10 @@ public class GardenProblemTypeServiceImpl implements GardenProblemTypeService { entity.setStatus(CommonStatusEnum.ENABLE.getStatus()); gardenProblemTypeMapper.insert(entity); count++; + } else if (!Objects.equals(exist.getTypeName(), dict.getLabel())) { + exist.setTypeName(dict.getLabel()); + gardenProblemTypeMapper.updateById(exist); + count++; } } return count;