Commit 5968c962c8cb563f4847a3846d4de5b38baf9305
Merge branch 'dev' of http://gitlab1.renniting.cn/JCSS/urbanops into dev
Showing
3 changed files
with
59 additions
and
9 deletions
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; | @@ -6,6 +6,8 @@ import com.zteits.urbanops.framework.mybatis.core.mapper.BaseMapperX; | ||
| 6 | import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypePageReqVO; | 6 | import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypePageReqVO; |
| 7 | import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; | 7 | import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; |
| 8 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | +import org.apache.ibatis.annotations.Param; | ||
| 10 | +import org.apache.ibatis.annotations.Select; | ||
| 9 | 11 | ||
| 10 | import java.util.ArrayList; | 12 | import java.util.ArrayList; |
| 11 | import java.util.List; | 13 | import java.util.List; |
| @@ -63,25 +65,55 @@ public interface GardenProblemTypeMapper extends BaseMapperX<GardenProblemTypeDO | @@ -63,25 +65,55 @@ public interface GardenProblemTypeMapper extends BaseMapperX<GardenProblemTypeDO | ||
| 63 | } | 65 | } |
| 64 | 66 | ||
| 65 | /** | 67 | /** |
| 68 | + * 根据名称、父级编码、层级查询记录(校验名称在同级下唯一) | ||
| 69 | + * 使用 LIMIT 1 避免已有脏数据导致 TooManyResultsException | ||
| 70 | + */ | ||
| 71 | + default GardenProblemTypeDO selectByNameAndParentAndLevel(String typeName, String parentCode, Integer level) { | ||
| 72 | + return selectOne(new LambdaQueryWrapperX<GardenProblemTypeDO>() | ||
| 73 | + .eq(GardenProblemTypeDO::getTypeName, typeName) | ||
| 74 | + .eq(GardenProblemTypeDO::getParentCode, parentCode) | ||
| 75 | + .eq(GardenProblemTypeDO::getLevel, level) | ||
| 76 | + .last("LIMIT 1")); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 绕过逻辑删除,直接查 typeCode 是否物理存在(用于编码生成时避免唯一键冲突) | ||
| 81 | + */ | ||
| 82 | + @Select("SELECT COUNT(1) FROM garden_problem_type WHERE type_code = #{code}") | ||
| 83 | + int countByTypeCodeRaw(@Param("code") String code); | ||
| 84 | + | ||
| 85 | + /** | ||
| 66 | * 生成下一个编码:父级编码 + 5位递增序号 | 86 | * 生成下一个编码:父级编码 + 5位递增序号 |
| 67 | * 如 parentCode=BIZ_GARDEN → BIZ_GARDEN00001, BIZ_GARDEN00002 | 87 | * 如 parentCode=BIZ_GARDEN → BIZ_GARDEN00001, BIZ_GARDEN00002 |
| 88 | + * 注意:加 LENGTH 条件避免匹配到子级编码;绕过逻辑删除检查确保唯一键可用 | ||
| 68 | */ | 89 | */ |
| 69 | default String generateNextCode(String parentCode) { | 90 | default String generateNextCode(String parentCode) { |
| 91 | + int expectedLength = parentCode.length() + 5; | ||
| 70 | List<GardenProblemTypeDO> list = selectList(new LambdaQueryWrapperX<GardenProblemTypeDO>() | 92 | List<GardenProblemTypeDO> list = selectList(new LambdaQueryWrapperX<GardenProblemTypeDO>() |
| 71 | .likeRight(GardenProblemTypeDO::getTypeCode, parentCode) | 93 | .likeRight(GardenProblemTypeDO::getTypeCode, parentCode) |
| 94 | + .apply("LENGTH(type_code) = {0}", expectedLength) | ||
| 72 | .orderByDesc(GardenProblemTypeDO::getTypeCode) | 95 | .orderByDesc(GardenProblemTypeDO::getTypeCode) |
| 73 | .last("LIMIT 1")); | 96 | .last("LIMIT 1")); |
| 97 | + int seq; | ||
| 74 | if (list == null || list.isEmpty()) { | 98 | if (list == null || list.isEmpty()) { |
| 75 | - return parentCode + "00001"; | ||
| 76 | - } | ||
| 77 | - String maxCode = list.get(0).getTypeCode(); | ||
| 78 | - String seqStr = maxCode.substring(parentCode.length()); | ||
| 79 | - try { | ||
| 80 | - int seq = Integer.parseInt(seqStr) + 1; | ||
| 81 | - return parentCode + String.format("%05d", seq); | ||
| 82 | - } catch (NumberFormatException e) { | ||
| 83 | - return parentCode + "00001"; | 99 | + seq = 1; |
| 100 | + } else { | ||
| 101 | + String maxCode = list.get(0).getTypeCode(); | ||
| 102 | + String seqStr = maxCode.substring(parentCode.length()); | ||
| 103 | + try { | ||
| 104 | + seq = Integer.parseInt(seqStr) + 1; | ||
| 105 | + } catch (NumberFormatException e) { | ||
| 106 | + seq = 1; | ||
| 107 | + } | ||
| 84 | } | 108 | } |
| 109 | + // 跳过被逻辑删除记录占用的编码 | ||
| 110 | + int maxAttempts = 100; | ||
| 111 | + String nextCode; | ||
| 112 | + do { | ||
| 113 | + nextCode = parentCode + String.format("%05d", seq); | ||
| 114 | + seq++; | ||
| 115 | + } while (countByTypeCodeRaw(nextCode) > 0 && --maxAttempts > 0); | ||
| 116 | + return nextCode; | ||
| 85 | } | 117 | } |
| 86 | 118 | ||
| 87 | } | 119 | } |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/ErrorCodeConstants.java
| @@ -150,6 +150,7 @@ public interface ErrorCodeConstants { | @@ -150,6 +150,7 @@ public interface ErrorCodeConstants { | ||
| 150 | // ========== 问题类型配置 1-100-009-000 ========== | 150 | // ========== 问题类型配置 1-100-009-000 ========== |
| 151 | ErrorCode PROBLEM_TYPE_NOT_EXISTS = new ErrorCode(1100009000, "问题类型不存在"); | 151 | ErrorCode PROBLEM_TYPE_NOT_EXISTS = new ErrorCode(1100009000, "问题类型不存在"); |
| 152 | ErrorCode PROBLEM_TYPE_CODE_EXISTS = new ErrorCode(1100009001, "问题类型编码已存在"); | 152 | ErrorCode PROBLEM_TYPE_CODE_EXISTS = new ErrorCode(1100009001, "问题类型编码已存在"); |
| 153 | + ErrorCode PROBLEM_TYPE_NAME_DUPLICATE = new ErrorCode(1100009002, "同级下问题类型名称已存在,一级、二级、三级类型名称不能同时重复"); | ||
| 153 | 154 | ||
| 154 | // ========== 一树一档案巡检与风险评估 1-100-008-000 ========== | 155 | // ========== 一树一档案巡检与风险评估 1-100-008-000 ========== |
| 155 | ErrorCode TREE_INSPECTION_NOT_EXISTS = new ErrorCode(1100008001, "巡检评估记录不存在"); | 156 | ErrorCode TREE_INSPECTION_NOT_EXISTS = new ErrorCode(1100008001, "巡检评估记录不存在"); |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/problemtype/GardenProblemTypeServiceImpl.java
| @@ -13,6 +13,7 @@ import jakarta.annotation.Resource; | @@ -13,6 +13,7 @@ import jakarta.annotation.Resource; | ||
| 13 | import java.util.ArrayList; | 13 | import java.util.ArrayList; |
| 14 | import java.util.List; | 14 | import java.util.List; |
| 15 | import java.util.Map; | 15 | import java.util.Map; |
| 16 | +import java.util.Objects; | ||
| 16 | import java.util.stream.Collectors; | 17 | import java.util.stream.Collectors; |
| 17 | 18 | ||
| 18 | import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; | 19 | import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; |
| @@ -43,6 +44,9 @@ public class GardenProblemTypeServiceImpl implements GardenProblemTypeService { | @@ -43,6 +44,9 @@ public class GardenProblemTypeServiceImpl implements GardenProblemTypeService { | ||
| 43 | public Long createProblemType(ProblemTypeSaveReqVO createReqVO) { | 44 | public Long createProblemType(ProblemTypeSaveReqVO createReqVO) { |
| 44 | // 校验编码唯一性 | 45 | // 校验编码唯一性 |
| 45 | validateTypeCodeUnique(createReqVO.getTypeCode(), null); | 46 | validateTypeCodeUnique(createReqVO.getTypeCode(), null); |
| 47 | + // 校验名称在同级父节点下唯一 | ||
| 48 | + validateTypeNameUniqueUnderParent(createReqVO.getTypeName(), | ||
| 49 | + createReqVO.getParentCode(), createReqVO.getLevel(), null); | ||
| 46 | // 插入 | 50 | // 插入 |
| 47 | GardenProblemTypeDO problemType = BeanUtils.toBean(createReqVO, GardenProblemTypeDO.class); | 51 | GardenProblemTypeDO problemType = BeanUtils.toBean(createReqVO, GardenProblemTypeDO.class); |
| 48 | gardenProblemTypeMapper.insert(problemType); | 52 | gardenProblemTypeMapper.insert(problemType); |
| @@ -81,6 +85,15 @@ public class GardenProblemTypeServiceImpl implements GardenProblemTypeService { | @@ -81,6 +85,15 @@ public class GardenProblemTypeServiceImpl implements GardenProblemTypeService { | ||
| 81 | } | 85 | } |
| 82 | } | 86 | } |
| 83 | 87 | ||
| 88 | + private void validateTypeNameUniqueUnderParent(String typeName, String parentCode, | ||
| 89 | + Integer level, Long excludeId) { | ||
| 90 | + GardenProblemTypeDO exist = gardenProblemTypeMapper.selectByNameAndParentAndLevel( | ||
| 91 | + typeName, parentCode, level); | ||
| 92 | + if (exist != null && (excludeId == null || !exist.getId().equals(excludeId))) { | ||
| 93 | + throw exception(PROBLEM_TYPE_NAME_DUPLICATE); | ||
| 94 | + } | ||
| 95 | + } | ||
| 96 | + | ||
| 84 | @Override | 97 | @Override |
| 85 | public GardenProblemTypeDO getProblemType(Long id) { | 98 | public GardenProblemTypeDO getProblemType(Long id) { |
| 86 | return gardenProblemTypeMapper.selectById(id); | 99 | return gardenProblemTypeMapper.selectById(id); |
| @@ -186,6 +199,10 @@ public class GardenProblemTypeServiceImpl implements GardenProblemTypeService { | @@ -186,6 +199,10 @@ public class GardenProblemTypeServiceImpl implements GardenProblemTypeService { | ||
| 186 | entity.setStatus(CommonStatusEnum.ENABLE.getStatus()); | 199 | entity.setStatus(CommonStatusEnum.ENABLE.getStatus()); |
| 187 | gardenProblemTypeMapper.insert(entity); | 200 | gardenProblemTypeMapper.insert(entity); |
| 188 | count++; | 201 | count++; |
| 202 | + } else if (!Objects.equals(exist.getTypeName(), dict.getLabel())) { | ||
| 203 | + exist.setTypeName(dict.getLabel()); | ||
| 204 | + gardenProblemTypeMapper.updateById(exist); | ||
| 205 | + count++; | ||
| 189 | } | 206 | } |
| 190 | } | 207 | } |
| 191 | return count; | 208 | return count; |