diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java index a1bc70846..54c82967c 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java @@ -32,82 +32,9 @@ public class GenConstants { */ public static final String PARENT_MENU_NAME = "parentMenuName"; - /** - * 数据库字符串类型 - */ - public static final String[] COLUMNTYPE_STR = {"char", "varchar", "nvarchar", "varchar2"}; - - /** - * 数据库文本类型 - */ - public static final String[] COLUMNTYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext"}; - - /** - * 数据库时间类型 - */ - public static final String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp"}; - - /** - * 数据库数字类型 - */ - public static final String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer", - "bit", "bigint", "float", "double", "decimal"}; - - /** - * 页面不需要编辑字段 - */ - public static final String[] COLUMNNAME_NOT_EDIT = {"id", "create_by", "create_time", "del_flag"}; - - /** - * 页面不需要显示的列表字段 - */ - public static final String[] COLUMNNAME_NOT_LIST = {"id", "create_by", "create_time", "del_flag", "update_by", - "update_time"}; - - /** - * 页面不需要查询字段 - */ - public static final String[] COLUMNNAME_NOT_QUERY = {"id", "create_by", "create_time", "del_flag", "update_by", - "update_time", "remark"}; - - /** - * Entity基类字段 - */ - public static final String[] BASE_ENTITY = {"createBy", "createTime", "updateBy", "updateTime", "remark"}; - /** * Tree基类字段 */ public static final String[] TREE_ENTITY = {"parentName", "parentId", "orderNum", "ancestors", "children"}; - /** - * 字符串类型 - */ - public static final String TYPE_STRING = "String"; - - /** - * 整型 - */ - public static final String TYPE_INTEGER = "Integer"; - - /** - * 长整型 - */ - public static final String TYPE_LONG = "Long"; - - /** - * 浮点型 - */ - public static final String TYPE_DOUBLE = "Double"; - - /** - * 高精度计算类型 - */ - public static final String TYPE_BIGDECIMAL = "BigDecimal"; - - /** - * 时间类型 - */ - public static final String TYPE_DATE = "Date"; - } diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java deleted file mode 100644 index 1aee0196c..000000000 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java +++ /dev/null @@ -1,218 +0,0 @@ -package com.ruoyi.generator.util; - -import java.util.Arrays; - -import org.apache.commons.lang3.RegExUtils; -import com.ruoyi.common.constant.GenConstants; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.generator.config.GenConfig; -import com.ruoyi.generator.domain.GenTable; -import com.ruoyi.generator.domain.GenTableColumn; - -/** - * 代码生成器 工具类 - * - * @author ruoyi - */ -public class GenUtils { - /** - * 初始化表信息 - */ - public static void initTable(GenTable genTable, String operName) { - genTable.setClassName(convertClassName(genTable.getTableName())); - genTable.setPackageName(GenConfig.getPackageName()); - genTable.setModuleName(getModuleName(GenConfig.getPackageName())); - genTable.setBusinessName(getBusinessName(genTable.getTableName())); - genTable.setFunctionName(replaceText(genTable.getTableComment())); - genTable.setFunctionAuthor(GenConfig.getAuthor()); - genTable.setCreateBy(operName); - } - - /** - * 初始化列属性字段 - */ - public static void initColumnField(GenTableColumn column, GenTable table) { - String dataType = getDbType(column.getColumnType()); - String columnName = column.getColumnName(); - column.setTableId(table.getTableId()); - column.setCreateBy(table.getCreateBy()); - // 设置java字段名 - column.setJavaField(StringUtils.toCamelCase(columnName)); - // 设置默认类型 - column.setJavaType(GenConstants.TYPE_STRING); - - if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType)) { - // 字符串长度超过500设置为文本域 - Integer columnLength = getColumnLength(column.getColumnType()); - String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT; - column.setHtmlType(htmlType); - } else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType)) { - column.setJavaType(GenConstants.TYPE_DATE); - column.setHtmlType(GenConstants.HTML_DATETIME); - } else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) { - column.setHtmlType(GenConstants.HTML_INPUT); - - // 如果是浮点型 统一用BigDecimal - String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ","); - if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) { - column.setJavaType(GenConstants.TYPE_BIGDECIMAL); - } - // 如果是整形 - else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) { - column.setJavaType(GenConstants.TYPE_INTEGER); - } - // 长整形 - else { - column.setJavaType(GenConstants.TYPE_LONG); - } - } - - // 插入字段(默认所有字段都需要插入) - column.setIsInsert(GenConstants.REQUIRE); - - // 编辑字段 - if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk()) { - column.setIsEdit(GenConstants.REQUIRE); - } - // 列表字段 - if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk()) { - column.setIsList(GenConstants.REQUIRE); - } - // 查询字段 - if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk()) { - column.setIsQuery(GenConstants.REQUIRE); - } - - // 查询字段类型 - if (StringUtils.endsWithIgnoreCase(columnName, "name")) { - column.setQueryType(GenConstants.QUERY_LIKE); - } - // 状态字段设置单选框 - if (StringUtils.endsWithIgnoreCase(columnName, "status")) { - column.setHtmlType(GenConstants.HTML_RADIO); - } - // 类型&性别字段设置下拉框 - else if (StringUtils.endsWithIgnoreCase(columnName, "type") - || StringUtils.endsWithIgnoreCase(columnName, "sex")) { - column.setHtmlType(GenConstants.HTML_SELECT); - } - // 文件字段设置上传控件 - else if (StringUtils.endsWithIgnoreCase(columnName, "image")) { - column.setHtmlType(GenConstants.HTML_UPLOAD_IMAGE); - } - // 内容字段设置富文本控件 - else if (StringUtils.endsWithIgnoreCase(columnName, "content")) { - column.setHtmlType(GenConstants.HTML_EDITOR); - } - } - - /** - * 校验数组是否包含指定值 - * - * @param arr 数组 - * @param targetValue 值 - * @return 是否包含 - */ - public static boolean arraysContains(String[] arr, String targetValue) { - return Arrays.asList(arr).contains(targetValue); - } - - /** - * 获取模块名 - * - * @param packageName 包名 - * @return 模块名 - */ - public static String getModuleName(String packageName) { - int lastIndex = packageName.lastIndexOf("."); - int nameLength = packageName.length(); - String moduleName = StringUtils.substring(packageName, lastIndex + 1, nameLength); - return moduleName; - } - - /** - * 获取业务名 - * - * @param tableName 表名 - * @return 业务名 - */ - public static String getBusinessName(String tableName) { - int lastIndex = tableName.lastIndexOf("_"); - int nameLength = tableName.length(); - String businessName = StringUtils.substring(tableName, lastIndex + 1, nameLength); - return businessName; - } - - /** - * 表名转换成Java类名 - * - * @param tableName 表名称 - * @return 类名 - */ - public static String convertClassName(String tableName) { - boolean autoRemovePre = GenConfig.getAutoRemovePre(); - String tablePrefix = GenConfig.getTablePrefix(); - if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix)) { - String[] searchList = StringUtils.split(tablePrefix, ","); - tableName = replaceFirst(tableName, searchList); - } - return StringUtils.convertToCamelCase(tableName); - } - - /** - * 批量替换前缀 - * - * @param replacementm 替换值 - * @param searchList 替换列表 - * @return - */ - public static String replaceFirst(String replacementm, String[] searchList) { - String text = replacementm; - for (String searchString : searchList) { - if (replacementm.startsWith(searchString)) { - text = replacementm.replaceFirst(searchString, ""); - break; - } - } - return text; - } - - /** - * 关键字替换 - * - * @param text 需要被替换的名字 - * @return 替换后的名字 - */ - public static String replaceText(String text) { - return RegExUtils.replaceAll(text, "(?:表|若依)", ""); - } - - /** - * 获取数据库类型字段 - * - * @param columnType 列类型 - * @return 截取后的列类型 - */ - public static String getDbType(String columnType) { - if (StringUtils.indexOf(columnType, "(") > 0) { - return StringUtils.substringBefore(columnType, "("); - } else { - return columnType; - } - } - - /** - * 获取字段长度 - * - * @param columnType 列类型 - * @return 截取后的列类型 - */ - public static Integer getColumnLength(String columnType) { - if (StringUtils.indexOf(columnType, "(") > 0) { - String length = StringUtils.substringBetween(columnType, "(", ")"); - return Integer.valueOf(length); - } else { - return 0; - } - } -} diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/ToolCodeGenController.java b/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/ToolCodeGenController.java index 9f142e101..1aa3165b4 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/ToolCodeGenController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/ToolCodeGenController.java @@ -3,19 +3,31 @@ package cn.iocoder.dashboard.modules.tool.controller.codegen; import cn.iocoder.dashboard.common.pojo.CommonResult; import cn.iocoder.dashboard.common.pojo.PageResult; import cn.iocoder.dashboard.modules.tool.controller.codegen.vo.ToolCodeGenTablePageItemRespVO; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import cn.iocoder.dashboard.modules.tool.service.codegen.ToolCodegenService; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; import static cn.iocoder.dashboard.common.pojo.CommonResult.success; @RestController -@RequestMapping("/tool/code-gen") +@RequestMapping("/tool/codegen") public class ToolCodeGenController { + @Resource + private ToolCodegenService codegenService; + @GetMapping("/table/page") public CommonResult> getCodeGenTablePage() { return success(null); } + @ApiOperation("基于数据库的表结构,创建代码生成器的表定义") + @PostMapping("/table/create") + // TODO 权限 + public CommonResult createCodeGenTable(@RequestParam("tableName") String tableName) { + return success(codegenService.createCodegenTable(tableName)); + } + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/convert/codegen/CodegenConvert.java b/src/main/java/cn/iocoder/dashboard/modules/tool/convert/codegen/CodegenConvert.java new file mode 100644 index 000000000..7f570db1e --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/tool/convert/codegen/CodegenConvert.java @@ -0,0 +1,21 @@ +package cn.iocoder.dashboard.modules.tool.convert.codegen; + +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenColumnDO; +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenTableDO; +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaColumnDO; +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaTableDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface CodegenConvert { + + CodegenConvert INSTANCE = Mappers.getMapper(CodegenConvert.class); + + ToolCodegenTableDO convert(ToolInformationSchemaTableDO bean); + + List convertList(List list); + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/convert/package-info.java b/src/main/java/cn/iocoder/dashboard/modules/tool/convert/package-info.java new file mode 100644 index 000000000..6dd9aa41b --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/tool/convert/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.dashboard.modules.tool.convert; diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolCodegenColumnMapper.java b/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolCodegenColumnMapper.java new file mode 100644 index 000000000..9e88678f4 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolCodegenColumnMapper.java @@ -0,0 +1,9 @@ +package cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen; + +import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenColumnDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ToolCodegenColumnMapper extends BaseMapperX { +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolCodegenTableMapper.java b/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolCodegenTableMapper.java new file mode 100644 index 000000000..a4e0dfe1a --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolCodegenTableMapper.java @@ -0,0 +1,15 @@ +package cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen; + +import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenTableDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ToolCodegenTableMapper extends BaseMapperX { + + default ToolCodegenTableDO selectByTableName(String tableName) { + return selectOne(new QueryWrapper().eq("table_name", tableName)); + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolInformationSchemaTableMapper.java b/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolInformationSchemaTableMapper.java index 05fe395d8..1aaed37e6 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolInformationSchemaTableMapper.java +++ b/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolInformationSchemaTableMapper.java @@ -14,4 +14,8 @@ public interface ToolInformationSchemaTableMapper extends BaseMapperX().eq("table_schema", tableSchema)); } + default ToolInformationSchemaTableDO selectByTableName(String tableName) { + return selectOne(new QueryWrapper().eq("table_name", tableName)); + } + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/enums/codegen/ToolCodegenColumnHtmlTypeEnum.java b/src/main/java/cn/iocoder/dashboard/modules/tool/enums/codegen/ToolCodegenColumnHtmlTypeEnum.java index f1f791034..8eec060df 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/tool/enums/codegen/ToolCodegenColumnHtmlTypeEnum.java +++ b/src/main/java/cn/iocoder/dashboard/modules/tool/enums/codegen/ToolCodegenColumnHtmlTypeEnum.java @@ -16,13 +16,14 @@ public enum ToolCodegenColumnHtmlTypeEnum { RADIO("radio"), // 单选框 CHECKBOX("checkbox"), // 复选框 DATETIME("datetime"), // 日期控件 - UPLOAD_IMAGE("upload_image"), // 上传控件 + UPLOAD_IMAGE("upload_image"), // 上传图片 + UPLOAD_FILE("upload_file"), // 上传文件 EDITOR("editor"), // 富文本控件 ; /** * 条件 */ - private final String condition; + private final String type; } diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/ToolCodegenService.java b/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/ToolCodegenService.java new file mode 100644 index 000000000..cc12b0945 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/ToolCodegenService.java @@ -0,0 +1,18 @@ +package cn.iocoder.dashboard.modules.tool.service.codegen; + +/** + * 代码生成 Service 接口 + * + * @author 芋道源码 + */ +public interface ToolCodegenService { + + /** + * 基于数据库的表结构,创建代码生成器的表定义 + * + * @param tableName 表名称 + * @return 表定义的编号 + */ + Long createCodegenTable(String tableName); + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java new file mode 100644 index 000000000..d1094539d --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java @@ -0,0 +1,222 @@ +package cn.iocoder.dashboard.modules.tool.service.codegen.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.dashboard.modules.tool.convert.codegen.CodegenConvert; +import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolCodegenColumnMapper; +import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolCodegenTableMapper; +import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolInformationSchemaColumnMapper; +import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolInformationSchemaTableMapper; +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenColumnDO; +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenTableDO; +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaColumnDO; +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaTableDO; +import cn.iocoder.dashboard.modules.tool.enums.codegen.ToolCodegenColumnHtmlTypeEnum; +import cn.iocoder.dashboard.modules.tool.enums.codegen.ToolCodegenColumnListConditionEnum; +import cn.iocoder.dashboard.modules.tool.service.codegen.ToolCodegenService; +import com.google.common.collect.Sets; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.*; + +/** + * 代码生成 Service 实现类 + * + * @author 芋道源码 + */ +@Service +public class ToolCodegenServiceImpl implements ToolCodegenService { + + /** + * 字段名与 {@link ToolCodegenColumnListConditionEnum} 的默认映射 + * 注意,字段的匹配以后缀的方式 + */ + private static final Map columnListOperationConditionMappings = + MapUtil.builder() + .put("name", ToolCodegenColumnListConditionEnum.LIKE) + .put("time", ToolCodegenColumnListConditionEnum.BETWEEN) + .put("date", ToolCodegenColumnListConditionEnum.BETWEEN) + .build(); + + /** + * 字段名与 {@link ToolCodegenColumnHtmlTypeEnum} 的默认映射 + * 注意,字段的匹配以后缀的方式 + */ + private static final Map columnHtmlTypeMappings = + MapUtil.builder() + .put("status", ToolCodegenColumnHtmlTypeEnum.RADIO) + .put("sex", ToolCodegenColumnHtmlTypeEnum.RADIO) + .put("type", ToolCodegenColumnHtmlTypeEnum.SELECT) + .put("image", ToolCodegenColumnHtmlTypeEnum.UPLOAD_IMAGE) + .put("file", ToolCodegenColumnHtmlTypeEnum.UPLOAD_FILE) + .put("content", ToolCodegenColumnHtmlTypeEnum.EDITOR) + .build(); + + /** + * 新增操作,不需要传递的字段 + */ + private static final Set CREATE_OPERATION_EXCLUDE_COLUMN = Sets.newHashSet( + "id"); + /** + * 修改操作,不需要传递的字段 + */ + private static final Set UPDATE_OPERATION_EXCLUDE_COLUMN = Sets.newHashSet(); + /** + * 列表操作的条件,不需要传递的字段 + */ + private static final Set LIST_OPERATION_CONDITION_COLUMN = Sets.newHashSet(); + /** + * 列表操作的结果,不需要返回的字段 + */ + private static final Set LIST_OPERATION_RESULT_COLUMN = Sets.newHashSet(); + + /** + * Java 类型与 MySQL 类型的映射关系 + */ + private static final Map> javaTypeMappings = MapUtil.>builder() + .put(Boolean.class.getSimpleName(), Sets.newHashSet("bit")) + .put(Integer.class.getSimpleName(), Sets.newHashSet("tinyint", "smallint", "mediumint", "int")) + .put(Long.class.getSimpleName(), Collections.singleton("bigint")) + .put(Double.class.getSimpleName(), Sets.newHashSet("float", "double")) + .put(BigDecimal.class.getSimpleName(), Sets.newHashSet("decimal", "numeric")) + .put(String.class.getSimpleName(), Sets.newHashSet("tinytext", "text", "mediumtext", "longtext", // 长文本 + "char", "varchar", "nvarchar", "varchar2")) // 短文本 + .put(Date.class.getSimpleName(), Sets.newHashSet("datetime", "time", "date", "timestamp")) + .build(); + + static { + Arrays.stream(BaseDO.class.getDeclaredFields()).forEach(field -> { + CREATE_OPERATION_EXCLUDE_COLUMN.add(field.getName()); + UPDATE_OPERATION_EXCLUDE_COLUMN.add(field.getName()); + LIST_OPERATION_CONDITION_COLUMN.add(field.getName()); + LIST_OPERATION_RESULT_COLUMN.add(field.getName()); + }); + LIST_OPERATION_RESULT_COLUMN.remove("create_time"); // 创建时间,还是需要返回的 + } + + @Resource + private ToolInformationSchemaTableMapper informationSchemaTableMapper; + @Resource + private ToolInformationSchemaColumnMapper informationSchemaColumnMapper; + @Resource + private ToolCodegenTableMapper codegenTableMapper; + @Resource + private ToolCodegenColumnMapper codegenColumnMapper; + + @Override + @Transactional + public Long createCodegenTable(String tableName) { + // 从数据库中,获得数据库表结构 + ToolInformationSchemaTableDO schemaTable = informationSchemaTableMapper.selectByTableName(tableName); + if (schemaTable == null) { + throw new RuntimeException(""); // TODO + } + List schemaColumns = informationSchemaColumnMapper.selectListByTableName(tableName); + if (CollUtil.isEmpty(schemaColumns)) { + throw new RuntimeException(""); // TODO + } + // 校验是否已经存在 + if (codegenTableMapper.selectByTableName(tableName) != null) { + throw new RuntimeException(""); // TODO + } + + // 将 table 插入到数据库 + ToolCodegenTableDO table = CodegenConvert.INSTANCE.convert(schemaTable); + initTableDefault(table); + codegenTableMapper.insert(table); + // 将 column 插入到数据库 + List columns = CodegenConvert.INSTANCE.convertList(schemaColumns); + columns.forEach(column -> { + initColumnDefault(column); + column.setTableId(table.getId()); + codegenColumnMapper.insert(column); + }); + return table.getId(); + } + + /** + * 初始化 Table 表的默认字段 + * + * @param table 表定义 + */ + private void initTableDefault(ToolCodegenTableDO table) { + table.setModuleName(StrUtil.subBefore(table.getTableName(), + '_', false)); // 第一个 _ 前缀的前面,作为 module 名字 + table.setBusinessName(StrUtil.subAfter(table.getTableName(), + '_', false)); // 第一个 _ 前缀的后面,作为 module 名字 + table.setBusinessName(StrUtil.toCamelCase(table.getBusinessName())); // 可能存在多个 _ 的情况,转换成驼峰 + table.setClassName(StrUtil.toCamelCase(table.getClassName())); // 驼峰 + table.setClassComment(StrUtil.subBefore(table.getClassComment(), // 去除结尾的表,作为类描述 + '表', true)); + table.setAuthor("芋艿"); // TODO 稍后改成创建人 + } + + /** + * 初始化 Column 列的默认字段 + * + * @param column 列定义 + */ + private void initColumnDefault(ToolCodegenColumnDO column) { + // 处理 Java 相关的字段的默认值 + processColumnJava(column); + // 处理 CRUD 相关的字段的默认值 + processColumnOperation(column); + // 处理 UI 相关的字段的默认值 + processColumnUI(column); + } + + private void processColumnJava(ToolCodegenColumnDO column) { + // 处理 javaField 字段 + column.setJavaField(StrUtil.toCamelCase(column.getColumnName())); + // 处理 dictType 字段,暂无 + // 处理 javaType 字段 + String dbType = StrUtil.subBefore(column.getColumnName(), ')', false); + javaTypeMappings.entrySet().stream() + .filter(entry -> entry.getValue().contains(dbType)) + .findFirst().ifPresent(entry -> column.setJavaType(entry.getKey())); + if (column.getJavaType() == null) { + throw new IllegalStateException(String.format("column(%s) 的数据库类型(%s) 找不到匹配的 Java 类型", + column.getColumnName(), column.getColumnType())); + } + } + + private void processColumnOperation(ToolCodegenColumnDO column) { + // 处理 createOperation 字段 + column.setCreateOperation(!CREATE_OPERATION_EXCLUDE_COLUMN.contains(column.getColumnName()) + && !column.getPrimaryKey()); // 非主键 + // 处理 updateOperation 字段 + column.setUpdateOperation(!UPDATE_OPERATION_EXCLUDE_COLUMN.contains(column.getColumnName())); + // 处理 listOperationResult 字段 + column.setListOperationResult(!LIST_OPERATION_RESULT_COLUMN.contains(column.getColumnName())); + // 处理 listOperationCondition 字段。默认设置为需要过滤的条件,手动进行取消 + if (!LIST_OPERATION_CONDITION_COLUMN.contains(column.getColumnName()) + && !column.getPrimaryKey()) { // 非主键 + column.setListOperationCondition(ToolCodegenColumnListConditionEnum.EQ.getCondition()); + } + columnListOperationConditionMappings.entrySet().stream() + .filter(entry -> StrUtil.endWithIgnoreCase(column.getColumnName(), entry.getKey())) + .findFirst().ifPresent(entry -> column.setListOperationCondition(entry.getValue().getCondition())); + } + + private void processColumnUI(ToolCodegenColumnDO column) { + // 基于后缀进行匹配 + columnHtmlTypeMappings.entrySet().stream() + .filter(entry -> StrUtil.endWithIgnoreCase(column.getColumnName(), entry.getKey())) + .findFirst().ifPresent(entry -> column.setHtmlType(entry.getValue().getType())); + // 如果是 Boolean 类型时,设置为 radio 类型. + // 其它类型,因为字段名可以相对保障,所以不进行处理。例如说 date 对应 datetime 类型. + if (Boolean.class.getSimpleName().equals(column.getJavaType())) { + column.setHtmlType(ToolCodegenColumnHtmlTypeEnum.RADIO.getType()); + } + // 兜底,设置默认为 input 类型 + if (column.getHtmlType() == null) { + column.setHtmlType(ToolCodegenColumnHtmlTypeEnum.INPUT.getType()); + } + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/service/package-info.java b/src/main/java/cn/iocoder/dashboard/modules/tool/service/package-info.java new file mode 100644 index 000000000..5c89d1db5 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/tool/service/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.dashboard.modules.tool.service;