Skip to content

Commit

Permalink
feat(tool/generator): 代码生成新增生成预览功能
Browse files Browse the repository at this point in the history
  • Loading branch information
Charles7c committed Dec 19, 2023
1 parent e719d20 commit 4017029
Show file tree
Hide file tree
Showing 8 changed files with 464 additions and 95 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* 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:https://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.charles7c.continew.admin.tool.model.resp;

import java.io.Serial;
import java.io.Serializable;

import lombok.Data;

import io.swagger.v3.oas.annotations.media.Schema;

import com.fasterxml.jackson.annotation.JsonIgnore;

/**
* 生成预览信息
*
* @author Charles7c
* @since 2023/12/19 21:34
*/
@Data
@Schema(description = "生成预览信息")
public class GeneratePreviewResp implements Serializable {

@Serial
private static final long serialVersionUID = 1L;

/**
* 文件名
*/
@Schema(description = "文件名", example = "UserController.java")
private String fileName;

/**
* 内容
*/
@Schema(description = "内容", example = "public class UserController {...}")
private String content;

/**
* 是否为后端代码
*/
@Schema(hidden = true)
@JsonIgnore
private boolean backend;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import top.charles7c.continew.admin.tool.model.entity.GenConfigDO;
import top.charles7c.continew.admin.tool.model.query.TableQuery;
import top.charles7c.continew.admin.tool.model.req.GenConfigReq;
import top.charles7c.continew.admin.tool.model.resp.GeneratePreviewResp;
import top.charles7c.continew.admin.tool.model.resp.TableResp;
import top.charles7c.continew.starter.extension.crud.model.query.PageQuery;
import top.charles7c.continew.starter.extension.crud.model.resp.PageDataResp;
Expand Down Expand Up @@ -80,6 +81,15 @@ public interface GeneratorService {
*/
void saveConfig(GenConfigReq req, String tableName);

/**
* 生成预览
*
* @param tableName
* 表名称
* @return 预览信息
*/
List<GeneratePreviewResp> preview(String tableName);

/**
* 生成代码
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import top.charles7c.continew.admin.tool.model.entity.GenConfigDO;
import top.charles7c.continew.admin.tool.model.query.TableQuery;
import top.charles7c.continew.admin.tool.model.req.GenConfigReq;
import top.charles7c.continew.admin.tool.model.resp.GeneratePreviewResp;
import top.charles7c.continew.admin.tool.model.resp.TableResp;
import top.charles7c.continew.admin.tool.service.GeneratorService;
import top.charles7c.continew.starter.core.constant.StringConstants;
Expand Down Expand Up @@ -85,7 +86,8 @@ public PageDataResp<TableResp> pageTable(TableQuery query, PageQuery pageQuery)
if (StrUtil.isNotBlank(tableName)) {
tableList.removeIf(table -> !StrUtil.containsAny(table.getTableName(), tableName));
}
tableList.removeIf(table -> StrUtil.equalsAny(table.getTableName(), generatorProperties.getExcludeTables()));
tableList.removeIf(
table -> StrUtil.equalsAnyIgnoreCase(table.getTableName(), generatorProperties.getExcludeTables()));
CollUtil.sort(tableList,
Comparator.comparing(Table::getCreateTime)
.thenComparing(table -> Optional.ofNullable(table.getUpdateTime()).orElse(table.getCreateTime()))
Expand Down Expand Up @@ -209,7 +211,9 @@ public void saveConfig(GenConfigReq req, String tableName) {
}

@Override
public void generate(String tableName) {
public List<GeneratePreviewResp> preview(String tableName) {
List<GeneratePreviewResp> generatePreviewList = new ArrayList<>();
// 初始化配置
GenConfigDO genConfig = genConfigMapper.selectById(tableName);
CheckUtils.throwIfNull(genConfig, "请先进行数据表 [{}] 生成配置", tableName);
List<FieldConfigDO> fieldConfigList = fieldConfigMapper.selectListByTableName(tableName);
Expand All @@ -221,68 +225,107 @@ public void generate(String tableName) {
StrUtil.subSuf(packageName, StrUtil.lastIndexOfIgnoreCase(packageName, StringConstants.DOT) + 1);
genConfigMap.put("apiModuleName", apiModuleName);
genConfigMap.put("apiName", StrUtil.lowerFirst(genConfig.getClassNamePrefix()));
// 渲染后端代码
String classNamePrefix = genConfig.getClassNamePrefix();
Map<String, TemplateConfig> templateConfigMap = generatorProperties.getTemplateConfigs();
for (Map.Entry<String, TemplateConfig> templateConfigEntry : templateConfigMap.entrySet()) {
this.pretreatment(genConfigMap, fieldConfigList, templateConfigEntry);
String className = classNamePrefix + StrUtil.nullToEmpty(templateConfigEntry.getKey());
genConfigMap.put("className", className);
TemplateConfig templateConfig = templateConfigEntry.getValue();
String content = TemplateUtils.render(templateConfig.getTemplatePath(), genConfigMap);
GeneratePreviewResp codePreview = new GeneratePreviewResp();
codePreview.setFileName(className + FileNameUtil.EXT_JAVA);
codePreview.setContent(content);
codePreview.setBackend(true);
generatePreviewList.add(codePreview);
}
// 渲染前端代码
// api 代码
genConfigMap.put("fieldConfigs", fieldConfigList);
String apiContent = TemplateUtils.render("generator/api.ftl", genConfigMap);
GeneratePreviewResp apiCodePreview = new GeneratePreviewResp();
apiCodePreview.setFileName(classNamePrefix.toLowerCase() + ".ts");
apiCodePreview.setContent(apiContent);
generatePreviewList.add(apiCodePreview);
// view 代码
String viewContent = TemplateUtils.render("generator/index.ftl", genConfigMap);
GeneratePreviewResp viewCodePreview = new GeneratePreviewResp();
viewCodePreview.setFileName("index.vue");
viewCodePreview.setContent(viewContent);
generatePreviewList.add(viewCodePreview);
return generatePreviewList;
}

@Override
public void generate(String tableName) {
// 初始化配置及数据
List<GeneratePreviewResp> generatePreviewList = this.preview(tableName);
GenConfigDO genConfig = genConfigMapper.selectById(tableName);
Boolean isOverride = genConfig.getIsOverride();
// 生成代码
String packageName = genConfig.getPackageName();
try {
String classNamePrefix = genConfig.getClassNamePrefix();
Boolean isOverride = genConfig.getIsOverride();
// 生成后端代码
// 1、确定后端代码基础路径
String classNamePrefix = genConfig.getClassNamePrefix();
// 1.确定后端代码基础路径
// 例如:D:/continew-admin
String projectPath = SystemUtil.getUserInfo().getCurrentDir();
// 例如:D:/continew-admin/continew-admin-tool
File backendModuleFile = new File(projectPath, genConfig.getModuleName());
// 例如:D:/continew-admin/continew-admin-tool/src/main/java/top/charles7c/continew/admin/tool
List<String> backendModuleChildPathList = CollUtil.newArrayList("src", "main", "java");
backendModuleChildPathList.addAll(StrUtil.split(genConfig.getPackageName(), StringConstants.DOT));
backendModuleChildPathList.addAll(StrUtil.split(packageName, StringConstants.DOT));
File backendParentFile =
FileUtil.file(backendModuleFile, backendModuleChildPathList.toArray(new String[0]));
// 2、生成代码
// 2.生成代码
List<GeneratePreviewResp> backendCodePreviewList =
generatePreviewList.stream().filter(GeneratePreviewResp::isBackend).collect(Collectors.toList());
Map<String, TemplateConfig> templateConfigMap = generatorProperties.getTemplateConfigs();
for (Map.Entry<String, TemplateConfig> templateConfigEntry : templateConfigMap.entrySet()) {
for (GeneratePreviewResp codePreview : backendCodePreviewList) {
// 例如:D:/continew-admin/continew-admin-tool/src/main/java/top/charles7c/continew/admin/tool/service/impl/XxxServiceImpl.java
this.pretreatment(genConfigMap, fieldConfigList, templateConfigEntry);
String className = classNamePrefix + StrUtil.nullToEmpty(templateConfigEntry.getKey());
genConfigMap.put("className", className);
TemplateConfig templateConfig = templateConfigEntry.getValue();
TemplateConfig templateConfig =
templateConfigMap.get(codePreview.getFileName().replace(classNamePrefix, StringConstants.EMPTY)
.replace(FileNameUtil.EXT_JAVA, StringConstants.EMPTY));
File classParentFile = FileUtil.file(backendParentFile,
StrUtil.splitToArray(templateConfig.getPackageName(), StringConstants.DOT));
File classFile = new File(classParentFile, className + FileNameUtil.EXT_JAVA);
File classFile = new File(classParentFile, codePreview.getFileName());
// 如果已经存在,且不允许覆盖,则跳过
if (classFile.exists() && !isOverride) {
continue;
}
String content = TemplateUtils.render(templateConfig.getTemplatePath(), genConfigMap);
FileUtil.writeString(content, classFile, StandardCharsets.UTF_8);
FileUtil.writeString(codePreview.getContent(), classFile, StandardCharsets.UTF_8);
}

// 生成前端代码
String frontendPath = genConfig.getFrontendPath();
if (StrUtil.isBlank(frontendPath)) {
return;
}
// 1、生成 api 代码
List<GeneratePreviewResp> frontendCodePreviewList =
generatePreviewList.stream().filter(p -> !p.isBackend()).collect(Collectors.toList());
// 1.生成 api 代码
String apiModuleName =
StrUtil.subSuf(packageName, StrUtil.lastIndexOfIgnoreCase(packageName, StringConstants.DOT) + 1);
GeneratePreviewResp apiCodePreview = frontendCodePreviewList.get(0);
// 例如:D:/continew-admin/continew-admin-ui
genConfigMap.put("fieldConfigs", fieldConfigList);
List<String> frontendSubPathList = StrUtil.split(frontendPath, "src");
String frontendModulePath = frontendSubPathList.get(0);
// 例如:D:/continew-admin/continew-admin-ui/src/api/tool/xxx.ts
File apiParentFile = FileUtil.file(frontendModulePath, "src", "api", apiModuleName);
String apiFileName = classNamePrefix.toLowerCase() + ".ts";
File apiFile = new File(apiParentFile, apiFileName);
File apiFile = new File(apiParentFile, apiCodePreview.getFileName());
if (apiFile.exists() && !isOverride) {
return;
}
String apiContent = TemplateUtils.render("generator/api.ftl", genConfigMap);
FileUtil.writeString(apiContent, apiFile, StandardCharsets.UTF_8);
// 2、生成 view 代码
FileUtil.writeString(apiCodePreview.getContent(), apiFile, StandardCharsets.UTF_8);
// 2.生成 view 代码
GeneratePreviewResp viewCodePreview = frontendCodePreviewList.get(1);
// 例如:D:/continew-admin/continew-admin-ui/src/views/tool/xxx/index.vue
File indexFile =
FileUtil.file(frontendPath, apiModuleName, StrUtil.lowerFirst(classNamePrefix), "index.vue");
if (indexFile.exists() && !isOverride) {
return;
}
String indexContent = TemplateUtils.render("generator/index.ftl", genConfigMap);
FileUtil.writeString(indexContent, indexFile, StandardCharsets.UTF_8);
FileUtil.writeString(viewCodePreview.getContent(), indexFile, StandardCharsets.UTF_8);
} catch (Exception e) {
log.error("Generate code occurred an error: {}. tableName: {}.", e.getMessage(), tableName, e);
throw new BusinessException("代码生成失败,请手动清理生成文件");
Expand Down
4 changes: 4 additions & 0 deletions continew-admin-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@
},
"dependencies": {
"@arco-design/web-vue": "^2.53.0",
"@codemirror/lang-java": "^6.0.1",
"@codemirror/lang-javascript": "^6.2.1",
"@kangc/v-md-editor": "^2.3.17",
"@vueuse/core": "^10.5.0",
"axios": "^0.24.0",
"codemirror": "^6.0.1",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.10",
"echarts": "^5.4.3",
Expand All @@ -46,6 +49,7 @@
"query-string": "^8.1.0",
"sortablejs": "^1.15.0",
"vue": "^3.3.7",
"vue-codemirror": "^6.1.1",
"vue-cropper": "^1.1.1",
"vue-echarts": "^6.6.1",
"vue-i18n": "^9.6.5",
Expand Down
Loading

0 comments on commit 4017029

Please sign in to comment.