refactor(generator): 优化代码生成列配置代码,取消后端部分默认值

This commit is contained in:
2024-08-30 20:05:59 +08:00
parent bd7bf43134
commit f5ee2b5beb
13 changed files with 205 additions and 100 deletions

View File

@@ -157,19 +157,22 @@ public class FieldConfigDO implements Serializable {
public FieldConfigDO(@NonNull Column column) {
this.setTableName(column.getTableName());
this.setColumnName(column.getName());
this.setColumnType(StrUtil.splitToArray(column.getTypeName(), StringConstants.SPACE)[0].toLowerCase());
this.setColumnType(column.getTypeName());
this.setColumnSize(Convert.toStr(column.getSize()));
this.setComment(column.getComment());
this.setIsRequired(!column.isPk() && !column.isNullable());
this.setShowInList(true);
this.setShowInForm(this.getIsRequired());
this.setShowInQuery(this.getIsRequired());
this.setFormType(FormTypeEnum.INPUT);
this.setQueryType("String".equals(this.getFieldType()) ? QueryTypeEnum.LIKE : QueryTypeEnum.EQ);
}
public void setColumnName(String columnName) {
this.columnName = columnName;
this.fieldName = StrUtil.toCamelCase(this.columnName);
}
public void setColumnType(String columnType) {
String[] arr = StrUtil.splitToArray(columnType, StringConstants.SPACE);
this.columnType = arr.length > 1 ? arr[0].toLowerCase() : columnType.toLowerCase();
}
}

View File

@@ -16,20 +16,15 @@
package top.continew.admin.generator.model.entity;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.validator.constraints.Length;
import top.continew.admin.common.constant.RegexConstants;
import top.continew.starter.core.util.StrUtils;
import java.io.Serial;
import java.io.Serializable;
@@ -118,21 +113,7 @@ public class GenConfigDO implements Serializable {
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
/**
* 类名前缀
*/
@Setter(AccessLevel.NONE)
@JsonIgnore
@TableField(exist = false)
private String classNamePrefix;
public GenConfigDO(String tableName) {
this.tableName = tableName;
}
public String getClassNamePrefix() {
String rawClassName = StrUtils.blankToDefault(this.tablePrefix, this.tableName, prefix -> StrUtil
.removePrefix(this.tableName, prefix));
return StrUtil.upperFirst(StrUtil.toCamelCase(rawClassName));
}
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.generator.model.entity;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
import lombok.EqualsAndHashCode;
import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.core.util.StrUtils;
import java.io.Serial;
import java.util.List;
import java.util.Set;
/**
* 内部生成配置信息
*
* @author zhangqcc
* @since 2024/8/30 19:35
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class InnerGenConfigDO extends GenConfigDO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 字段配置信息
*/
private List<FieldConfigDO> fieldConfigs;
/**
* 生成时间
*/
private String datetime;
/**
* API 模块名称
*/
private String apiModuleName;
/**
* API 名称
*/
private String apiName;
/**
* 类名
*/
private String className;
/**
* 类名前缀
*/
private String classNamePrefix;
/**
* 子包名称
*/
private String subPackageName;
/**
* 字典编码列表
*/
private Set<String> dictCodes;
/**
* 是否包含必填字段
*/
private boolean hasRequiredField;
/**
* 是否包含字典字段
*/
private boolean hasDictField;
/**
* 是否包含 BigDecimal 字段
*/
private boolean hasBigDecimalField;
/**
* 是否包含 List 字段
*/
private boolean hasListField;
/**
* 是否包含 Time 包字段
*/
private boolean hasTimeField;
public InnerGenConfigDO() {
}
public InnerGenConfigDO(GenConfigDO genConfig) {
BeanUtil.copyProperties(genConfig, this);
this.setDatetime(DateUtil.date().toString("yyyy/MM/dd HH:mm"));
this.setApiName(StrUtil.lowerFirst(this.getClassNamePrefix()));
}
@Override
public void setPackageName(String packageName) {
super.setPackageName(packageName);
String realPackageName = this.getPackageName();
this.setApiModuleName(StrUtil.subSuf(realPackageName, StrUtil
.lastIndexOfIgnoreCase(realPackageName, StringConstants.DOT) + 1));
}
public String getClassNamePrefix() {
String tableName = super.getTableName();
String rawClassName = StrUtils.blankToDefault(super.getTablePrefix(), tableName, prefix -> StrUtil
.removePrefix(tableName, prefix));
return StrUtil.upperFirst(StrUtil.toCamelCase(rawClassName));
}
}

View File

@@ -19,9 +19,9 @@ package top.continew.admin.generator.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.db.meta.Column;
@@ -33,11 +33,13 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.continew.admin.generator.config.properties.GeneratorProperties;
import top.continew.admin.generator.enums.FormTypeEnum;
import top.continew.admin.generator.enums.QueryTypeEnum;
import top.continew.admin.generator.mapper.FieldConfigMapper;
import top.continew.admin.generator.mapper.GenConfigMapper;
import top.continew.admin.generator.model.entity.FieldConfigDO;
import top.continew.admin.generator.model.entity.GenConfigDO;
import top.continew.admin.generator.model.entity.InnerGenConfigDO;
import top.continew.admin.generator.model.query.TableQuery;
import top.continew.admin.generator.model.req.GenConfigReq;
import top.continew.admin.generator.model.resp.GeneratePreviewResp;
@@ -78,6 +80,7 @@ public class GeneratorServiceImpl implements GeneratorService {
private final ProjectProperties projectProperties;
private final FieldConfigMapper fieldConfigMapper;
private final GenConfigMapper genConfigMapper;
private static final List<String> TIME_PACKAGE_CLASS = Arrays.asList("LocalDate", "LocalTime", "LocalDateTime");
@Override
public PageResp<TableResp> pageTable(TableQuery query, PageQuery pageQuery) throws SQLException {
@@ -154,8 +157,7 @@ public class GeneratorServiceImpl implements GeneratorService {
.orElseGet(() -> new FieldConfigDO(column));
// 更新已有字段配置
if (null != fieldConfig.getCreateTime()) {
String columnType = StrUtil.splitToArray(column.getTypeName(), StringConstants.SPACE)[0].toLowerCase();
fieldConfig.setColumnType(columnType);
fieldConfig.setColumnType(column.getTypeName());
fieldConfig.setColumnSize(Convert.toStr(column.getSize()));
}
String fieldType = typeMappingEntrySet.stream()
@@ -181,14 +183,14 @@ public class GeneratorServiceImpl implements GeneratorService {
// 重新设置排序
fieldConfig.setFieldSort(i + 1);
if (Boolean.TRUE.equals(fieldConfig.getShowInForm())) {
CheckUtils.throwIfNull(fieldConfig.getFormType(), "字段 [{}] 的表单类型不能为空", fieldConfig.getFieldName());
fieldConfig.setFormType(ObjectUtil.defaultIfNull(fieldConfig.getFormType(), FormTypeEnum.INPUT));
} else {
// 在表单中不显示,不需要设置必填
fieldConfig.setIsRequired(false);
}
if (Boolean.TRUE.equals(fieldConfig.getShowInQuery())) {
CheckUtils.throwIfNull(fieldConfig.getFormType(), "字段 [{}] 的表单类型不能为空", fieldConfig.getFieldName());
CheckUtils.throwIfNull(fieldConfig.getQueryType(), "字段 [{}] 的查询方式不能为空", fieldConfig.getFieldName());
fieldConfig.setFormType(ObjectUtil.defaultIfNull(fieldConfig.getFormType(), FormTypeEnum.INPUT));
fieldConfig.setQueryType(ObjectUtil.defaultIfNull(fieldConfig.getQueryType(), QueryTypeEnum.EQ));
} else {
// 在查询中不显示,不需要设置查询方式
fieldConfig.setQueryType(null);
@@ -220,21 +222,24 @@ public class GeneratorServiceImpl implements GeneratorService {
CheckUtils.throwIfNull(genConfig, "请先进行数据表 [{}] 生成配置", tableName);
List<FieldConfigDO> fieldConfigList = fieldConfigMapper.selectListByTableName(tableName);
CheckUtils.throwIfEmpty(fieldConfigList, "请先进行数据表 [{}] 字段配置", tableName);
Map<String, Object> genConfigMap = BeanUtil.beanToMap(genConfig);
genConfigMap.put("date", DateUtil.date().toString("yyyy/MM/dd HH:mm"));
String packageName = genConfig.getPackageName();
String apiModuleName = StrUtil.subSuf(packageName, StrUtil
.lastIndexOfIgnoreCase(packageName, StringConstants.DOT) + 1);
genConfigMap.put("apiModuleName", apiModuleName);
genConfigMap.put("apiName", StrUtil.lowerFirst(genConfig.getClassNamePrefix()));
InnerGenConfigDO innerGenConfig = new InnerGenConfigDO(genConfig);
// 渲染代码
String classNamePrefix = genConfig.getClassNamePrefix();
String classNamePrefix = innerGenConfig.getClassNamePrefix();
Map<String, GeneratorProperties.TemplateConfig> templateConfigMap = generatorProperties.getTemplateConfigs();
for (Map.Entry<String, GeneratorProperties.TemplateConfig> templateConfigEntry : templateConfigMap.entrySet()) {
this.pretreatment(genConfigMap, fieldConfigList, templateConfigEntry);
String className = classNamePrefix + StrUtil.nullToEmpty(templateConfigEntry.getKey());
genConfigMap.put("className", className);
GeneratorProperties.TemplateConfig templateConfig = templateConfigEntry.getValue();
// 移除需要忽略的字段
innerGenConfig.setFieldConfigs(fieldConfigList.stream()
.filter(fieldConfig -> !StrUtil.equalsAny(fieldConfig.getFieldName(), templateConfig
.getExcludeFields()))
.toList());
// 预处理配置
this.pretreatment(innerGenConfig);
// 处理其他配置
innerGenConfig.setSubPackageName(templateConfig.getPackageName());
String classNameSuffix = templateConfigEntry.getKey();
String className = classNamePrefix + classNameSuffix;
innerGenConfig.setClassName(className);
boolean isBackend = templateConfig.isBackend();
String extension = templateConfig.getExtension();
GeneratePreviewResp generatePreview = new GeneratePreviewResp();
@@ -242,29 +247,28 @@ public class GeneratorServiceImpl implements GeneratorService {
generatePreviewList.add(generatePreview);
if (isBackend) {
generatePreview.setFileName(className + extension);
generatePreview.setContent(TemplateUtils.render(templateConfig.getTemplatePath(), genConfigMap));
generatePreview.setContent(TemplateUtils.render(templateConfig.getTemplatePath(), BeanUtil
.beanToMap(innerGenConfig)));
} else {
generatePreview.setFileName(".vue".equals(extension) && "index".equals(templateConfigEntry.getKey())
generatePreview.setFileName(".vue".equals(extension) && "index".equals(classNameSuffix)
? "index.vue"
: this.getFrontendFileName(classNamePrefix, className, extension));
genConfigMap.put("fieldConfigs", fieldConfigList);
generatePreview.setContent(TemplateUtils.render(templateConfig.getTemplatePath(), genConfigMap));
innerGenConfig.setFieldConfigs(fieldConfigList);
generatePreview.setContent(TemplateUtils.render(templateConfig.getTemplatePath(), BeanUtil
.beanToMap(innerGenConfig)));
}
setPreviewPath(generatePreview, genConfig, templateConfig);
setPreviewPath(generatePreview, innerGenConfig, templateConfig);
}
return generatePreviewList;
}
private void setPreviewPath(GeneratePreviewResp generatePreview,
GenConfigDO genConfig,
InnerGenConfigDO genConfig,
GeneratorProperties.TemplateConfig templateConfig) {
// 获取前后端基础路径
String backendBasicPackagePath = this.buildBackendBasicPackagePath(genConfig);
String frontendBasicPackagePath = String.join(File.separator, projectProperties.getAppName(), projectProperties
.getAppName() + "-ui");
String packageName = genConfig.getPackageName();
String moduleName = StrUtil.subSuf(packageName, StrUtil
.lastIndexOfIgnoreCase(packageName, StringConstants.DOT) + 1);
String packagePath;
if (generatePreview.isBackend()) {
// 例如continew-admin/continew-system/src/main/java/top/continew/admin/system/service/impl
@@ -273,7 +277,7 @@ public class GeneratorServiceImpl implements GeneratorService {
} else {
// 例如continew-admin/continew-admin-ui/src/views/system
packagePath = String.join(File.separator, frontendBasicPackagePath, templateConfig.getPackageName()
.replace(StringConstants.SLASH, File.separator), moduleName);
.replace(StringConstants.SLASH, File.separator), genConfig.getApiModuleName());
// 例如continew-admin/continew-admin-ui/src/views/system/user
packagePath = ".vue".equals(templateConfig.getExtension())
? packagePath + File.separator + StrUtil.lowerFirst(genConfig.getClassNamePrefix())
@@ -352,51 +356,36 @@ public class GeneratorServiceImpl implements GeneratorService {
/**
* 预处理生成配置
*
* @param genConfigMap 生成配置
* @param originFieldConfigList 原始字段配置列表
* @param templateConfigEntry 模板配置
* @param genConfig 生成配置
*/
private void pretreatment(Map<String, Object> genConfigMap,
List<FieldConfigDO> originFieldConfigList,
Map.Entry<String, GeneratorProperties.TemplateConfig> templateConfigEntry) {
GeneratorProperties.TemplateConfig templateConfig = templateConfigEntry.getValue();
// 移除需要忽略的字段
List<FieldConfigDO> fieldConfigList = originFieldConfigList.stream()
.filter(fieldConfig -> !StrUtil.equalsAny(fieldConfig.getFieldName(), templateConfig.getExcludeFields()))
.toList();
genConfigMap.put("fieldConfigs", fieldConfigList);
private void pretreatment(InnerGenConfigDO genConfig) {
List<FieldConfigDO> fieldConfigList = genConfig.getFieldConfigs();
// 统计部分特殊字段特征
genConfigMap.put("hasLocalDateTimeField", false);
genConfigMap.put("hasBigDecimalField", false);
genConfigMap.put("hasRequiredField", false);
genConfigMap.put("hasListField", false);
genConfigMap.put("hasDictField", false);
Set<String> dictCodeSet = new HashSet<>();
for (FieldConfigDO fieldConfig : fieldConfigList) {
String fieldType = fieldConfig.getFieldType();
if ("LocalDateTime".equals(fieldType)) {
genConfigMap.put("hasLocalDateTimeField", true);
}
if ("BigDecimal".equals(fieldType)) {
genConfigMap.put("hasBigDecimalField", true);
}
// 必填项
if (Boolean.TRUE.equals(fieldConfig.getIsRequired())) {
genConfigMap.put("hasRequiredField", true);
genConfig.setHasRequiredField(true);
}
// 字典码
if (StrUtil.isNotBlank(fieldConfig.getDictCode())) {
genConfigMap.put("hasDictField", true);
dictCodeSet.add(fieldConfig.getDictCode());
// 数据类型
if ("BigDecimal".equals(fieldType)) {
genConfig.setHasBigDecimalField(true);
}
if (TIME_PACKAGE_CLASS.contains(fieldType)) {
genConfig.setHasTimeField(true);
}
QueryTypeEnum queryType = fieldConfig.getQueryType();
if (null != queryType && StrUtil.equalsAny(queryType.name(), QueryTypeEnum.IN.name(), QueryTypeEnum.NOT_IN
.name(), QueryTypeEnum.BETWEEN.name())) {
genConfigMap.put("hasListField", true);
genConfig.setHasListField(true);
}
// 字典码
if (StrUtil.isNotBlank(fieldConfig.getDictCode())) {
genConfig.setHasDictField(true);
dictCodeSet.add(fieldConfig.getDictCode());
}
}
genConfigMap.put("dictCodes", dictCodeSet);
String subPackageName = templateConfig.getPackageName();
genConfigMap.put("subPackageName", subPackageName);
genConfig.setDictCodes(dictCodeSet);
}
}

View File

@@ -18,7 +18,7 @@ import ${packageName}.service.${classNamePrefix}Service;
* ${businessName}管理 API
*
* @author ${author}
* @since ${date}
* @since ${datetime}
*/
@Tag(name = "${businessName}管理 API")
@RestController

View File

@@ -1,8 +1,8 @@
package ${packageName}.${subPackageName};
import java.io.Serial;
<#if hasLocalDateTimeField>
import java.time.LocalDateTime;
<#if hasTimeField>
import java.time.*;
</#if>
<#if hasBigDecimalField>
import java.math.BigDecimal;
@@ -21,7 +21,7 @@ import top.continew.starter.extension.crud.model.resp.BaseDetailResp;
* ${businessName}详情信息
*
* @author ${author}
* @since ${date}
* @since ${datetime}
*/
@Data
@ExcelIgnoreUnannotated

View File

@@ -1,8 +1,8 @@
package ${packageName}.${subPackageName};
import java.io.Serial;
<#if hasLocalDateTimeField>
import java.time.LocalDateTime;
<#if hasTimeField>
import java.time.*;
</#if>
<#if hasBigDecimalField>
import java.math.BigDecimal;
@@ -18,7 +18,7 @@ import top.continew.starter.extension.crud.model.entity.BaseDO;
* ${businessName}实体
*
* @author ${author}
* @since ${date}
* @since ${datetime}
*/
@Data
@TableName("${tableName}")

View File

@@ -7,6 +7,6 @@ import ${packageName}.model.entity.${classNamePrefix}DO;
* ${businessName} Mapper
*
* @author ${author}
* @since ${date}
* @since ${datetime}
*/
public interface ${className} extends BaseMapper<${classNamePrefix}DO> {}

View File

@@ -2,8 +2,8 @@ package ${packageName}.${subPackageName};
import java.io.Serial;
import java.io.Serializable;
<#if hasLocalDateTimeField>
import java.time.LocalDateTime;
<#if hasTimeField>
import java.time.*;
</#if>
<#if hasBigDecimalField>
import java.math.BigDecimal;
@@ -23,7 +23,7 @@ import top.continew.starter.data.core.enums.QueryType;
* ${businessName}查询条件
*
* @author ${author}
* @since ${date}
* @since ${datetime}
*/
@Data
@Schema(description = "${businessName}查询条件")

View File

@@ -1,8 +1,8 @@
package ${packageName}.${subPackageName};
import java.io.Serial;
<#if hasLocalDateTimeField>
import java.time.LocalDateTime;
<#if hasTimeField>
import java.time.*;
</#if>
<#if hasBigDecimalField>
import java.math.BigDecimal;
@@ -24,7 +24,7 @@ import top.continew.starter.extension.crud.model.req.BaseReq;
* 创建或修改${businessName}信息
*
* @author ${author}
* @since ${date}
* @since ${datetime}
*/
@Data
@Schema(description = "创建或修改${businessName}信息")

View File

@@ -1,8 +1,8 @@
package ${packageName}.${subPackageName};
import java.io.Serial;
<#if hasLocalDateTimeField>
import java.time.LocalDateTime;
<#if hasTimeField>
import java.time.*;
</#if>
<#if hasBigDecimalField>
import java.math.BigDecimal;
@@ -18,7 +18,7 @@ import top.continew.starter.extension.crud.model.resp.BaseResp;
* ${businessName}信息
*
* @author ${author}
* @since ${date}
* @since ${datetime}
*/
@Data
@Schema(description = "${businessName}信息")

View File

@@ -10,6 +10,6 @@ import ${packageName}.model.resp.${classNamePrefix}Resp;
* ${businessName}业务接口
*
* @author ${author}
* @since ${date}
* @since ${datetime}
*/
public interface ${className} extends BaseService<${classNamePrefix}Resp, ${classNamePrefix}DetailResp, ${classNamePrefix}Query, ${classNamePrefix}Req> {}

View File

@@ -17,7 +17,7 @@ import ${packageName}.service.${classNamePrefix}Service;
* ${businessName}业务实现
*
* @author ${author}
* @since ${date}
* @since ${datetime}
*/
@Service
@RequiredArgsConstructor