feat: 新增编码生成核心引擎
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
package cn.code.nl.module.base.service.codegen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码生成 Service 接口
|
||||||
|
*
|
||||||
|
* @author zhouz
|
||||||
|
*/
|
||||||
|
public interface CodeGenService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据规则编码生成编码字符串
|
||||||
|
*
|
||||||
|
* @param ruleCode 规则编码
|
||||||
|
* @return 生成的编码
|
||||||
|
*/
|
||||||
|
String generate(String ruleCode);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
package cn.code.nl.module.base.service.codegen;
|
||||||
|
|
||||||
|
import cn.code.nl.module.base.dal.dataobject.codegen.CodeRuleDO;
|
||||||
|
import cn.code.nl.module.base.service.codegen.dto.DateSegment;
|
||||||
|
import cn.code.nl.module.base.service.codegen.dto.PrefixSegment;
|
||||||
|
import cn.code.nl.module.base.service.codegen.dto.SegmentConfig;
|
||||||
|
import cn.code.nl.module.base.service.codegen.dto.SequenceSegment;
|
||||||
|
import cn.code.nl.module.base.service.codegen.enums.LetterCaseEnum;
|
||||||
|
import cn.code.nl.module.base.service.codegen.enums.SeqStrategyEnum;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.code.nl.module.base.enums.ErrorCodeConstants.CODE_GEN_LENGTH_EXCEED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码生成引擎实现类
|
||||||
|
*
|
||||||
|
* @author zhouz
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@Validated
|
||||||
|
public class CodeGenServiceImpl implements CodeGenService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CodeRuleService codeRuleService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SequenceAllocator sequenceAllocator;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generate(String ruleCode) {
|
||||||
|
// 1. 获取规则配置(带缓存)
|
||||||
|
CodeRuleDO rule = codeRuleService.getRuleByCode(ruleCode);
|
||||||
|
|
||||||
|
// 2. 遍历分段配置,逐段生成
|
||||||
|
List<SegmentConfig> segments = rule.getSegmentConfig();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < segments.size(); i++) {
|
||||||
|
String segmentValue = buildSegment(rule, segments.get(i));
|
||||||
|
sb.append(segmentValue);
|
||||||
|
// 段之间加分隔符
|
||||||
|
if (i < segments.size() - 1 && StrUtil.isNotBlank(rule.getSeparator())) {
|
||||||
|
sb.append(rule.getSeparator());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 后处理
|
||||||
|
return postProcess(sb.toString(), rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据段类型分发处理,生成段值
|
||||||
|
*/
|
||||||
|
private String buildSegment(CodeRuleDO rule, SegmentConfig segment) {
|
||||||
|
return switch (segment.getType()) {
|
||||||
|
case "PREFIX" -> buildPrefixSegment((PrefixSegment) segment);
|
||||||
|
case "DATE" -> buildDateSegment((DateSegment) segment);
|
||||||
|
case "SEQUENCE" -> buildSequenceSegment(rule, (SequenceSegment) segment);
|
||||||
|
default -> throw new IllegalArgumentException("不支持的段类型: " + segment.getType());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成固定前缀段
|
||||||
|
*/
|
||||||
|
private String buildPrefixSegment(PrefixSegment segment) {
|
||||||
|
return segment.getValue() != null ? segment.getValue() : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成日期段
|
||||||
|
*/
|
||||||
|
private String buildDateSegment(DateSegment segment) {
|
||||||
|
String format = StrUtil.isNotBlank(segment.getFormat())
|
||||||
|
? segment.getFormat() : "yyyyMMdd";
|
||||||
|
return LocalDate.now().format(DateTimeFormatter.ofPattern(format));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成流水序号段
|
||||||
|
*/
|
||||||
|
private String buildSequenceSegment(CodeRuleDO rule, SequenceSegment segment) {
|
||||||
|
String strategy = rule.getSeqStrategy();
|
||||||
|
if (SeqStrategyEnum.LOCK.getCode().equals(strategy)) {
|
||||||
|
return sequenceAllocator.allocateByLock(rule.getId(), segment);
|
||||||
|
}
|
||||||
|
return sequenceAllocator.allocateBySegment(rule.getId(), segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后处理:大小写转换 + 总长度校验
|
||||||
|
*/
|
||||||
|
private String postProcess(String code, CodeRuleDO rule) {
|
||||||
|
// 大小写转换
|
||||||
|
if (rule.getLetterCase() != null && rule.getLetterCase() == LetterCaseEnum.UPPER.getCode()) {
|
||||||
|
code = code.toUpperCase();
|
||||||
|
} else if (rule.getLetterCase() != null && rule.getLetterCase() == LetterCaseEnum.LOWER.getCode()) {
|
||||||
|
code = code.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 总长度校验
|
||||||
|
if (rule.getTotalLength() != null && rule.getTotalLength() > 0 && code.length() > rule.getTotalLength()) {
|
||||||
|
log.error("生成的编码超出总长度限制,code={}, length={}, maxLength={}",
|
||||||
|
code, code.length(), rule.getTotalLength());
|
||||||
|
throw exception(CODE_GEN_LENGTH_EXCEED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user