diff --git a/shgx-dryingroom/src/main/java/com/shgx/dryingroom/web/service/impl/DryParamThresholdServiceImpl.java b/shgx-dryingroom/src/main/java/com/shgx/dryingroom/web/service/impl/DryParamThresholdServiceImpl.java index 238f8a7..2704d02 100644 --- a/shgx-dryingroom/src/main/java/com/shgx/dryingroom/web/service/impl/DryParamThresholdServiceImpl.java +++ b/shgx-dryingroom/src/main/java/com/shgx/dryingroom/web/service/impl/DryParamThresholdServiceImpl.java @@ -58,7 +58,10 @@ public class DryParamThresholdServiceImpl implements IDryParamThresholdService { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(dryParamThreshold); - return dryParamThresholdMapper.selectList(queryWrapper.orderByDesc(DryParamThreshold::getRuleCode)); + return dryParamThresholdMapper.selectList(queryWrapper + .orderByDesc(DryParamThreshold::getIsEnabled) + .orderByDesc(DryParamThreshold::getCreateTime) + .orderByDesc(DryParamThreshold::getUpdateTime)); } /** @@ -70,13 +73,31 @@ public class DryParamThresholdServiceImpl implements IDryParamThresholdService @Override public int insertDryParamThreshold(DryParamThreshold dryParamThreshold) { + // 校验 ruleName 是否已存在于数据库 + String ruleName = dryParamThreshold.getRuleName().trim(); + LambdaQueryWrapper ruleNameQuery = new LambdaQueryWrapper() + .eq(DryParamThreshold::getRuleName, ruleName); + long ruleNameCount = dryParamThresholdMapper.selectCount(ruleNameQuery); + if (ruleNameCount > 0) { + throw new RuntimeException(String.format("规则名称【%s】已存在,请更换名称后重试", ruleName)); + } + + // 校验 materialName 是否已存在于数据库 + String materialName = dryParamThreshold.getMaterialName().trim(); + LambdaQueryWrapper materialNameQuery = new LambdaQueryWrapper() + .eq(DryParamThreshold::getMaterialName, materialName); + long materialNameCount = dryParamThresholdMapper.selectCount(materialNameQuery); + if (materialNameCount > 0) { + throw new RuntimeException(String.format("物料名称【%s】已存在,请更换名称后重试", materialName)); + } + // 接入MES后使用 // dryParamThreshold.setWorkOrderCode(""); // dryParamThreshold.setProductCode(""); // 自动生成规则代码和物料代码 - dryParamThreshold.setRuleCode(generateUniqueCode(dryParamThreshold.getRuleName(), null, dryParamThresholdMapper, code -> new LambdaQueryWrapper().eq(DryParamThreshold::getRuleCode, code))); - dryParamThreshold.setMaterialCode(generateUniqueCode(null, dryParamThreshold.getMaterialName(), dryParamThresholdMapper, code -> new LambdaQueryWrapper().eq(DryParamThreshold::getMaterialCode, code))); + dryParamThreshold.setRuleCode(generateUniqueCode(dryParamThreshold.getRuleName(), null, dryParamThresholdMapper)); + dryParamThreshold.setMaterialCode(generateUniqueCode(null, dryParamThreshold.getMaterialName(), dryParamThresholdMapper)); dryParamThreshold.setCreateBy(SecurityUtils.getUsername()); dryParamThreshold.setCreateTime(DateUtils.getNowDate()); @@ -93,6 +114,23 @@ public class DryParamThresholdServiceImpl implements IDryParamThresholdService @Override public int updateDryParamThreshold(DryParamThreshold dryParamThreshold) { + String ruleName = dryParamThreshold.getRuleName().trim(); + LambdaQueryWrapper ruleNameQuery = new LambdaQueryWrapper() + .eq(DryParamThreshold::getRuleName, ruleName); + long ruleNameCount = dryParamThresholdMapper.selectCount(ruleNameQuery); + if (ruleNameCount > 0) { + throw new RuntimeException(String.format("规则名称【%s】已存在,请更换名称后重试", ruleName)); + } + + // 校验 materialName 是否已存在于数据库 + String materialName = dryParamThreshold.getMaterialName().trim(); + LambdaQueryWrapper materialNameQuery = new LambdaQueryWrapper() + .eq(DryParamThreshold::getMaterialName, materialName); + long materialNameCount = dryParamThresholdMapper.selectCount(materialNameQuery); + if (materialNameCount > 0) { + throw new RuntimeException(String.format("物料名称【%s】已存在,请更换名称后重试", materialName)); + } + dryParamThreshold.setUpdateBy(SecurityUtils.getUsername()); dryParamThreshold.setUpdateTime(DateUtils.getNowDate()); @@ -126,140 +164,119 @@ public class DryParamThresholdServiceImpl implements IDryParamThresholdService } /** - * 根据名称和类型生成唯一 ruleCode / materialCode,自动查重,重复提示 - * @param ruleName 规则名称(如 rulename 对应 "用户注册规则",materialname 对应 "不锈钢板材") + * 生成唯一 ruleCode / materialCode + * @param ruleName 规则名称 * @param materialName 物料名称 - * @param dryParamThresholdMapper - * @return 唯一编码 + * @param mapper DryParamThresholdMapper 实例 + * @return 纯英文唯一编码 * @throws RuntimeException 输入非法或编码重复 */ public static String generateUniqueCode(String ruleName, String materialName, - com.baomidou.mybatisplus.core.mapper.BaseMapper dryParamThresholdMapper, - java.util.function.Function queryWrapperFunc) { + com.baomidou.mybatisplus.core.mapper.BaseMapper mapper) { + // 1. 确定编码类型、名称、前缀 String name; String prefix; - if (ruleName == null) { - name = materialName; - prefix = "MATERIAL_"; - } else { - name = ruleName; + boolean isRuleCode; + if (ruleName != null && !ruleName.trim().isEmpty()) { + name = ruleName.trim(); prefix = "RULE_"; + isRuleCode = true; + } else if (materialName != null && !materialName.trim().isEmpty()) { + name = materialName.trim(); + prefix = "MATERIAL_"; + isRuleCode = false; + } else { + throw new RuntimeException("输入名称不能为空(ruleName 和 materialName 不能同时为空)"); } - // 1. 输入校验 - if (name == null || name.trim().isEmpty()) { - throw new RuntimeException("输入名称不能为空"); + // 2. 名称预处理:清理特殊字符 + 中文转纯英文拼音(核心避免中文编码) + String cleanName = Pattern.compile("[^a-zA-Z0-9\u4e00-\u9fa5]").matcher(name).replaceAll(""); + String englishName = chineseToPinyin(cleanName); + if (englishName.isEmpty()) { + englishName = "DEF"; // 兜底,避免空拼音导致编码异常 } - // 清理名称中的特殊字符(保留中文、字母、数字) - String cleanName = Pattern.compile("[^a-zA-Z0-9\u4e00-\u9fa5]").matcher(name.trim()).replaceAll(""); - String englishName = chineseToFullPinyin(cleanName); // 中文转英文拼音 - int maxRetry = 3; // 最多重试3次,避免死循环 - - // 2. 生成编码 + 查重 + int maxRetry = 5; // 重试次数5次,降低重复概率 for (int i = 0; i < maxRetry; i++) { String candidateCode; - // 规则1:ruleName → RULE_名称前4字大写_8位随机码 - if (ruleName != null) { + // 3. 生成编码(按原规则,强化纯英文) + if (isRuleCode) { + // ruleCode:前缀_拼音前4位大写_6位随机码 String nameAbbr = englishName.length() > 4 ? englishName.substring(0, 4) : englishName; - nameAbbr = nameAbbr.toUpperCase(); // 转大写 - String randomSuffix = UUID.randomUUID().toString().substring(0, 8).toUpperCase(); + nameAbbr = nameAbbr.toUpperCase(); + String randomSuffix = UUID.randomUUID().toString().replace("-", "").substring(0, 6).toUpperCase(); candidateCode = String.format("%s%s_%s", prefix, nameAbbr, randomSuffix); - } - - // 规则2:materialName → MATERIAL_名称首字母大写_8位随机码 - else { + } else { + // materialCode:前缀_拼音首字母大写_6位随机码 StringBuilder initials = new StringBuilder(); boolean isFirstChar = true; for (char c : englishName.toCharArray()) { - // 仅取英文单词的首字母(拼音已无中文,直接判断字母) if (isFirstChar && Character.isLetter(c)) { initials.append(Character.toUpperCase(c)); isFirstChar = false; } else if (Character.isWhitespace(c)) { - isFirstChar = true; // 空格分隔后重新识别首字母 + isFirstChar = true; } } String initStr = initials.length() > 0 ? initials.toString() : "DEF"; - String randomSuffix = UUID.randomUUID().toString().substring(0, 8).toUpperCase(); + String randomSuffix = UUID.randomUUID().toString().replace("-", "").substring(0, 6).toUpperCase(); candidateCode = String.format("%s%s_%s", prefix, initStr, randomSuffix); } - // 查重 - long count; - LambdaQueryWrapper queryWrapper = queryWrapperFunc.apply(candidateCode); - count = dryParamThresholdMapper.selectCount(queryWrapper); + // 4. 同字段查重(核心:确保当前字段内无重复) + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (isRuleCode) { + queryWrapper.eq(DryParamThreshold::getRuleCode, candidateCode); + } else { + queryWrapper.eq(DryParamThreshold::getMaterialCode, candidateCode); + } - // 无重复则返回编码 + long count = mapper.selectCount(queryWrapper); if (count == 0) { - return candidateCode; + return candidateCode; // 无重复则返回 } } - // 重试3次仍重复,抛出明确提示 - throw new RuntimeException("生成失败:编码重复,请更换名称或稍后重试"); + // 重试5次仍重复,抛出明确异常 + String codeType = isRuleCode ? "ruleCode" : "materialCode"; + throw new RuntimeException(String.format("生成%s失败:编码重复(已重试5次),请更换名称或稍后重试", codeType)); } - /** - * 核心辅助方法:基于 pinyin4j 将中文转为完整拼音(无音调,纯英文) - * 支持:中文→全拼,英文直接保留,数字忽略(不影响编码格式) - */ - private static String chineseToFullPinyin(String input) { - if (input == null || input.isEmpty()) { + private static String chineseToPinyin(String chinese) { + if (chinese == null || chinese.isEmpty()) { return ""; } - // 配置拼音输出格式:无音调(如“张”→“zhang”,而非“zhang1”) + // 配置拼音格式:无音调(如“干”→“gan”,而非“gan1”) HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat(); format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); StringBuilder pinyin = new StringBuilder(); - for (char c : input.toCharArray()) { - // 英文直接保留 - if (Character.isLetter(c)) { - pinyin.append(c); - continue; - } - // 数字忽略(编码中已有随机码,数字无需参与拼音生成) - if (Character.isDigit(c)) { - continue; - } - // 中文转全拼(pinyin4j 支持所有常用中文) - try { - String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c, format); - if (pinyinArray != null && pinyinArray.length > 0) { - pinyin.append(pinyinArray[0]); // 取第一个拼音(多音字默认取第一个,可根据需求扩展) - } else { - pinyin.append("unknown"); // 极少数生僻字默认值(可调整) + for (char c : chinese.toCharArray()) { + // 中文汉字:转拼音 + if (Character.UnicodeBlock.of(c) == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS) { + try { + // 获取该汉字的所有拼音(多音字取第一个) + String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c, format); + if (pinyinArray != null && pinyinArray.length > 0) { + pinyin.append(pinyinArray[0]); // 取第一个拼音(如“行”→“xing”) + } else { + pinyin.append("unknown"); // 生僻字兜底 + } + } catch (BadHanyuPinyinOutputFormatCombination e) { + pinyin.append("unknown"); // 异常兜底 } - } catch (BadHanyuPinyinOutputFormatCombination e) { - pinyin.append("unknown"); // 异常情况兜底 + } else if (Character.isLetterOrDigit(c)) { + // 字母/数字:直接保留 + pinyin.append(c); + } else { + // 特殊字符:替换为下划线(后续会被清理,不影响编码) + pinyin.append("_"); } } - // 去除连续重复字符(如“AA”→“A”),避免拼音过长 - return removeContinuousDuplicates(pinyin.toString()).trim(); - } - - /** - * 辅助方法3:去除拼音中的连续重复字符(如“yongoong”→“yongong”,优化编码长度) - */ - private static String removeContinuousDuplicates(String str) { - if (str == null || str.length() <= 1) { - return str; - } - - StringBuilder sb = new StringBuilder(); - sb.append(str.charAt(0)); - for (int i = 1; i < str.length(); i++) { - char current = str.charAt(i); - char last = sb.charAt(sb.length() - 1); - if (current != last) { - sb.append(current); - } - } - return sb.toString(); + return pinyin.toString(); } }