diff --git a/pom.xml b/pom.xml index 03090260..1639be87 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.youlai youlai-boot - 3.0.0 + 3.1.0 基于 Java 17 + SpringBoot 3 + Spring Security 构建的权限管理系统。 @@ -271,4 +271,4 @@ - \ No newline at end of file + diff --git a/sql/mysql/youlai_boot.sql b/sql/mysql/youlai_boot.sql index bda59564..7a26fb14 100644 --- a/sql/mysql/youlai_boot.sql +++ b/sql/mysql/youlai_boot.sql @@ -451,9 +451,11 @@ CREATE TABLE `gen_config` ( `entity_name` varchar(100) NOT NULL COMMENT '实体类名', `author` varchar(50) NOT NULL COMMENT '作者', `parent_menu_id` bigint COMMENT '上级菜单ID,对应sys_menu的id ', + `remove_table_prefix` varchar(20) COMMENT '要移除的表前缀,如: sys_', + `page_type` varchar(20) COMMENT '页面类型(classic|curd)', `create_time` datetime COMMENT '创建时间', `update_time` datetime COMMENT '更新时间', - `is_deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', + `is_deleted` tinyint(4) DEFAULT 0 COMMENT '是否删除', PRIMARY KEY (`id`), UNIQUE KEY `uk_tablename` (`table_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='代码生成基础配置表'; diff --git a/src/main/java/com/youlai/boot/shared/codegen/controller/CodegenController.java b/src/main/java/com/youlai/boot/shared/codegen/controller/CodegenController.java index 50119908..76c57116 100644 --- a/src/main/java/com/youlai/boot/shared/codegen/controller/CodegenController.java +++ b/src/main/java/com/youlai/boot/shared/codegen/controller/CodegenController.java @@ -82,17 +82,19 @@ public class CodegenController { @Operation(summary = "获取预览生成代码") @GetMapping("/{tableName}/preview") @Log(value = "预览生成代码", module = LogModuleEnum.OTHER) - public Result> getTablePreviewData(@PathVariable String tableName) { - List list = codegenService.getCodegenPreviewData(tableName); + public Result> getTablePreviewData(@PathVariable String tableName, + @RequestParam(value = "pageType", required = false, defaultValue = "classic") String pageType) { + List list = codegenService.getCodegenPreviewData(tableName, pageType); return Result.success(list); } @Operation(summary = "下载代码") @GetMapping("/{tableName}/download") @Log(value = "下载代码", module = LogModuleEnum.OTHER) - public void downloadZip(HttpServletResponse response, @PathVariable String tableName) { + public void downloadZip(HttpServletResponse response, @PathVariable String tableName, + @RequestParam(value = "pageType", required = false, defaultValue = "classic") String pageType) { String[] tableNames = tableName.split(","); - byte[] data = codegenService.downloadCode(tableNames); + byte[] data = codegenService.downloadCode(tableNames, pageType); response.reset(); response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(codegenProperties.getDownloadFileName(), StandardCharsets.UTF_8)); diff --git a/src/main/java/com/youlai/boot/shared/codegen/converter/CodegenConverter.java b/src/main/java/com/youlai/boot/shared/codegen/converter/CodegenConverter.java index 0508ff99..7e33247b 100644 --- a/src/main/java/com/youlai/boot/shared/codegen/converter/CodegenConverter.java +++ b/src/main/java/com/youlai/boot/shared/codegen/converter/CodegenConverter.java @@ -23,6 +23,8 @@ public interface CodegenConverter { @Mapping(source = "genConfig.packageName", target = "packageName") @Mapping(source = "genConfig.entityName", target = "entityName") @Mapping(source = "genConfig.author", target = "author") + @Mapping(source = "genConfig.pageType", target = "pageType") + @Mapping(source = "genConfig.removeTablePrefix", target = "removeTablePrefix") @Mapping(source = "fieldConfigs", target = "fieldConfigs") GenConfigForm toGenConfigForm(GenConfig genConfig, List fieldConfigs); diff --git a/src/main/java/com/youlai/boot/shared/codegen/model/entity/GenConfig.java b/src/main/java/com/youlai/boot/shared/codegen/model/entity/GenConfig.java index 7fddaf12..45df1203 100644 --- a/src/main/java/com/youlai/boot/shared/codegen/model/entity/GenConfig.java +++ b/src/main/java/com/youlai/boot/shared/codegen/model/entity/GenConfig.java @@ -51,4 +51,14 @@ public class GenConfig extends BaseEntity { * 作者 */ private String author; + + /** + * 页面类型 classic|curd + */ + private String pageType; + + /** + * 要移除的表前缀,如: sys_ + */ + private String removeTablePrefix; } \ No newline at end of file diff --git a/src/main/java/com/youlai/boot/shared/codegen/model/form/GenConfigForm.java b/src/main/java/com/youlai/boot/shared/codegen/model/form/GenConfigForm.java index 2893788d..60a6dc03 100644 --- a/src/main/java/com/youlai/boot/shared/codegen/model/form/GenConfigForm.java +++ b/src/main/java/com/youlai/boot/shared/codegen/model/form/GenConfigForm.java @@ -50,6 +50,12 @@ public class GenConfigForm { @Schema(description = "前端应用名") private String frontendAppName; + @Schema(description = "页面类型 classic|curd", example = "classic") + private String pageType; + + @Schema(description = "要移除的表前缀,如: sys_", example = "sys_") + private String removeTablePrefix; + @Schema(description = "字段配置") @Data public static class FieldConfig { diff --git a/src/main/java/com/youlai/boot/shared/codegen/service/CodegenService.java b/src/main/java/com/youlai/boot/shared/codegen/service/CodegenService.java index ce48fde3..f42bc765 100644 --- a/src/main/java/com/youlai/boot/shared/codegen/service/CodegenService.java +++ b/src/main/java/com/youlai/boot/shared/codegen/service/CodegenService.java @@ -29,12 +29,12 @@ public interface CodegenService { * @param tableName 表名 * @return */ - List getCodegenPreviewData(String tableName); + List getCodegenPreviewData(String tableName, String pageType); /** * 下载代码 * @param tableNames 表名 * @return */ - byte[] downloadCode(String[] tableNames); + byte[] downloadCode(String[] tableNames, String pageType); } diff --git a/src/main/java/com/youlai/boot/shared/codegen/service/impl/CodegenServiceImpl.java b/src/main/java/com/youlai/boot/shared/codegen/service/impl/CodegenServiceImpl.java index 6ae9e04e..8e568714 100644 --- a/src/main/java/com/youlai/boot/shared/codegen/service/impl/CodegenServiceImpl.java +++ b/src/main/java/com/youlai/boot/shared/codegen/service/impl/CodegenServiceImpl.java @@ -2,6 +2,7 @@ package com.youlai.boot.shared.codegen.service.impl; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.template.Template; @@ -72,7 +73,7 @@ public class CodegenServiceImpl implements CodegenService { * @return 预览数据 */ @Override - public List getCodegenPreviewData(String tableName) { + public List getCodegenPreviewData(String tableName, String pageType) { List list = new ArrayList<>(); @@ -124,7 +125,9 @@ public class CodegenServiceImpl implements CodegenService { /* 3. 生成文件内容 */ // 将模板文件中的变量替换为具体的值 生成代码内容 - String content = getCodeContent(templateConfig, genConfig, fieldConfigs); + // 优先使用保存的 ui,没有则使用请求参数 + String finalType = StrUtil.blankToDefault(genConfig.getPageType(), pageType); + String content = getCodeContent(templateConfig, genConfig, fieldConfigs, finalType); previewVO.setContent(content); list.add(previewVO); @@ -146,7 +149,8 @@ public class CodegenServiceImpl implements CodegenService { } else if ("MapperXml".equals(templateName)) { return entityName + "Mapper" + extension; } else if ("API".equals(templateName)) { - return StrUtil.toSymbolCase(entityName, '-') + extension; + // 生成 user-api.ts 命名 + return StrUtil.toSymbolCase(entityName, '-') + "-api" + extension; } else if ("VIEW".equals(templateName)) { return "index.vue"; } @@ -211,7 +215,7 @@ public class CodegenServiceImpl implements CodegenService { * @param fieldConfigs 字段配置 * @return 代码内容 */ - private String getCodeContent(CodegenProperties.TemplateConfig templateConfig, GenConfig genConfig, List fieldConfigs) { + private String getCodeContent(CodegenProperties.TemplateConfig templateConfig, GenConfig genConfig, List fieldConfigs, String pageType) { Map bindMap = new HashMap<>(); @@ -252,7 +256,15 @@ public class CodegenServiceImpl implements CodegenService { bindMap.put("hasRequiredField", hasRequiredField); TemplateEngine templateEngine = TemplateUtil.createEngine(new TemplateConfig("templates", TemplateConfig.ResourceMode.CLASSPATH)); - Template template = templateEngine.getTemplate(templateConfig.getTemplatePath()); + // 根据 ui 选择不同的前端页面模板:默认 index.vue.vm;封装版使用 index.curd.vue.vm + String path = templateConfig.getTemplatePath(); + if ("VIEW".equals(FileNameUtil.mainName(path))) { + // 无法通过文件名区分时,依据子包名与扩展名判断 + } + if ("curd".equalsIgnoreCase(pageType) && path.endsWith("index.vue.vm")) { + path = path.replace("index.vue.vm", "index.curd.vue.vm"); + } + Template template = templateEngine.getTemplate(path); return template.render(bindMap); } @@ -264,13 +276,13 @@ public class CodegenServiceImpl implements CodegenService { * @return 压缩文件字节数组 */ @Override - public byte[] downloadCode(String[] tableNames) { + public byte[] downloadCode(String[] tableNames, String ui) { try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(outputStream)) { // 遍历每个表名,生成对应的代码并压缩到 zip 文件中 for (String tableName : tableNames) { - generateAndZipCode(tableName, zip); + generateAndZipCode(tableName, zip, ui); } // 确保所有压缩数据写入输出流,避免数据残留在内存缓冲区引发的数据不完整 zip.finish(); @@ -288,8 +300,8 @@ public class CodegenServiceImpl implements CodegenService { * @param tableName 表名 * @param zip 压缩文件输出流 */ - private void generateAndZipCode(String tableName, ZipOutputStream zip) { - List codePreviewList = getCodegenPreviewData(tableName); + private void generateAndZipCode(String tableName, ZipOutputStream zip, String ui) { + List codePreviewList = getCodegenPreviewData(tableName, ui); for (CodegenPreviewVO codePreview : codePreviewList) { String fileName = codePreview.getFileName(); diff --git a/src/main/java/com/youlai/boot/shared/codegen/service/impl/GenConfigServiceImpl.java b/src/main/java/com/youlai/boot/shared/codegen/service/impl/GenConfigServiceImpl.java index 906c2982..143f6372 100644 --- a/src/main/java/com/youlai/boot/shared/codegen/service/impl/GenConfigServiceImpl.java +++ b/src/main/java/com/youlai/boot/shared/codegen/service/impl/GenConfigServiceImpl.java @@ -83,8 +83,13 @@ public class GenConfigServiceImpl extends ServiceImpl SysUser - genConfig.setEntityName(StrUtil.toCamelCase(StrUtil.upperFirst(StrUtil.toCamelCase(tableName)))); + // 根据表名生成实体类名,支持去除前缀 例如:sys_user -> SysUser + String removePrefix = genConfig.getRemoveTablePrefix(); + String processedTable = tableName; + if (StrUtil.isNotBlank(removePrefix) && StrUtil.startWith(tableName, removePrefix)) { + processedTable = StrUtil.removePrefix(tableName, removePrefix); + } + genConfig.setEntityName(StrUtil.toCamelCase(StrUtil.upperFirst(StrUtil.toCamelCase(processedTable)))); genConfig.setPackageName(YouLaiBootApplication.class.getPackageName()); genConfig.setModuleName(codegenProperties.getDefaultConfig().getModuleName()); // 默认模块名 diff --git a/src/main/resources/templates/codegen/api.ts.vm b/src/main/resources/templates/codegen/api.ts.vm index afddcc9c..a80445e8 100644 --- a/src/main/resources/templates/codegen/api.ts.vm +++ b/src/main/resources/templates/codegen/api.ts.vm @@ -29,11 +29,11 @@ const ${entityName}API = { * * @param data ${businessName}表单数据 */ - add(data: ${entityName}Form) { + create(data: ${entityName}Form) { return request({ url: `${${entityName.toUpperCase()}_BASE_URL}`, method: "post", - data: data, + data, }); }, @@ -43,11 +43,11 @@ const ${entityName}API = { * @param id ${businessName}ID * @param data ${businessName}表单数据 */ - update(id: number, data: ${entityName}Form) { + update(id: string, data: ${entityName}Form) { return request({ url: `${${entityName.toUpperCase()}_BASE_URL}/${id}`, method: "put", - data: data, + data, }); }, diff --git a/src/main/resources/templates/codegen/index.curd.vue.vm b/src/main/resources/templates/codegen/index.curd.vue.vm new file mode 100644 index 00000000..5f05fa41 --- /dev/null +++ b/src/main/resources/templates/codegen/index.curd.vue.vm @@ -0,0 +1,119 @@ + + + + diff --git a/src/main/resources/templates/codegen/index.vue.vm b/src/main/resources/templates/codegen/index.vue.vm index 0c256c33..a398e4c3 100644 --- a/src/main/resources/templates/codegen/index.vue.vm +++ b/src/main/resources/templates/codegen/index.vue.vm @@ -2,9 +2,9 @@
- #foreach($fieldConfig in $fieldConfigs) - #if($fieldConfig.isShowInQuery == 1) - + #foreach($fieldConfig in $fieldConfigs) + #if($fieldConfig.isShowInQuery == 1) + #if($fieldConfig.formType == "INPUT") #elseif($fieldConfig.formType == "SELECT") #if($fieldConfig.dictType && $fieldConfig.dictType.trim() != "") - + #else @@ -23,7 +23,7 @@ #end #elseif($fieldConfig.formType == "RADIO") #if($fieldConfig.dictType && $fieldConfig.dictType.trim() != "") - + #else 选项一 @@ -32,7 +32,7 @@ #end #elseif($fieldConfig.formType == "CHECK_BOX") #if($fieldConfig.dictType && $fieldConfig.dictType.trim() != "") - + #else 选项一 @@ -85,18 +85,12 @@ value-format="YYYY-MM-DD" /> #end - - #end + #end - - - - 搜索 - - - - 重置 - + #end + + 搜索 + 重置
@@ -106,50 +100,46 @@ - - 新增 - + >新增 - - 删除 - + >删除
- #foreach($fieldConfig in $fieldConfigs) - #if($fieldConfig.isShowInList == 1) - #if($fieldConfig.dictType && $fieldConfig.dictType.trim() != "") - - - - #else - - #end - #end + #foreach($fieldConfig in $fieldConfigs) + #if($fieldConfig.isShowInList == 1) + #if($fieldConfig.dictType && $fieldConfig.dictType.trim() != "") + + + + #else + + #end #end + #end @@ -203,7 +193,7 @@ /> #elseif($fieldConfig.formType == "SELECT") #if($fieldConfig.dictType && $fieldConfig.dictType.trim() != "") - + #else @@ -212,7 +202,7 @@ #end #elseif($fieldConfig.formType == "RADIO") #if($fieldConfig.dictType && $fieldConfig.dictType.trim() != "") - + #else 选项一 @@ -221,7 +211,7 @@ #end #elseif($fieldConfig.formType == "CHECK_BOX") #if($fieldConfig.dictType && $fieldConfig.dictType.trim() != "") - + #else 选项一 @@ -283,7 +273,7 @@ inheritAttrs: false, }); - import ${entityName}API, { ${entityName}PageVO, ${entityName}Form, ${entityName}PageQuery } from "@/api/${moduleName}/${kebabCaseEntityName}"; + import ${entityName}API, { ${entityName}PageVO, ${entityName}Form, ${entityName}PageQuery } from "@/api/${moduleName}/${kebabCaseEntityName}-api"; const queryFormRef = ref(); const dataFormRef = ref();