Commit 5968c962c8cb563f4847a3846d4de5b38baf9305

Authored by 颜惠青
2 parents 70d77911 8212d7c2

Merge branch 'dev' of http://gitlab1.renniting.cn/JCSS/urbanops into dev

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 import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypePageReqVO;
7 7 import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO;
8 8 import org.apache.ibatis.annotations.Mapper;
  9 +import org.apache.ibatis.annotations.Param;
  10 +import org.apache.ibatis.annotations.Select;
9 11  
10 12 import java.util.ArrayList;
11 13 import java.util.List;
... ... @@ -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 86 * 生成下一个编码:父级编码 + 5位递增序号
67 87 * 如 parentCode=BIZ_GARDEN → BIZ_GARDEN00001, BIZ_GARDEN00002
  88 + * 注意:加 LENGTH 条件避免匹配到子级编码;绕过逻辑删除检查确保唯一键可用
68 89 */
69 90 default String generateNextCode(String parentCode) {
  91 + int expectedLength = parentCode.length() + 5;
70 92 List<GardenProblemTypeDO> list = selectList(new LambdaQueryWrapperX<GardenProblemTypeDO>()
71 93 .likeRight(GardenProblemTypeDO::getTypeCode, parentCode)
  94 + .apply("LENGTH(type_code) = {0}", expectedLength)
72 95 .orderByDesc(GardenProblemTypeDO::getTypeCode)
73 96 .last("LIMIT 1"));
  97 + int seq;
74 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 150 // ========== 问题类型配置 1-100-009-000 ==========
151 151 ErrorCode PROBLEM_TYPE_NOT_EXISTS = new ErrorCode(1100009000, "问题类型不存在");
152 152 ErrorCode PROBLEM_TYPE_CODE_EXISTS = new ErrorCode(1100009001, "问题类型编码已存在");
  153 + ErrorCode PROBLEM_TYPE_NAME_DUPLICATE = new ErrorCode(1100009002, "同级下问题类型名称已存在,一级、二级、三级类型名称不能同时重复");
153 154  
154 155 // ========== 一树一档案巡检与风险评估 1-100-008-000 ==========
155 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 13 import java.util.ArrayList;
14 14 import java.util.List;
15 15 import java.util.Map;
  16 +import java.util.Objects;
16 17 import java.util.stream.Collectors;
17 18  
18 19 import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO;
... ... @@ -43,6 +44,9 @@ public class GardenProblemTypeServiceImpl implements GardenProblemTypeService {
43 44 public Long createProblemType(ProblemTypeSaveReqVO createReqVO) {
44 45 // 校验编码唯一性
45 46 validateTypeCodeUnique(createReqVO.getTypeCode(), null);
  47 + // 校验名称在同级父节点下唯一
  48 + validateTypeNameUniqueUnderParent(createReqVO.getTypeName(),
  49 + createReqVO.getParentCode(), createReqVO.getLevel(), null);
46 50 // 插入
47 51 GardenProblemTypeDO problemType = BeanUtils.toBean(createReqVO, GardenProblemTypeDO.class);
48 52 gardenProblemTypeMapper.insert(problemType);
... ... @@ -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 97 @Override
85 98 public GardenProblemTypeDO getProblemType(Long id) {
86 99 return gardenProblemTypeMapper.selectById(id);
... ... @@ -186,6 +199,10 @@ public class GardenProblemTypeServiceImpl implements GardenProblemTypeService {
186 199 entity.setStatus(CommonStatusEnum.ENABLE.getStatus());
187 200 gardenProblemTypeMapper.insert(entity);
188 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 208 return count;
... ...