修改代码生成器包.

This commit is contained in:
lijiahang
2023-08-09 18:00:39 +08:00
parent 0063b31f35
commit 0f739f01e9
25 changed files with 204 additions and 63 deletions

View File

@@ -0,0 +1,355 @@
package com.orion.ops.launch.generator;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.orion.lang.constant.Const;
import com.orion.lang.utils.ext.yml.YmlExt;
import com.orion.ops.framework.mybatis.core.domain.BaseDO;
import com.orion.ops.framework.mybatis.core.mapper.IMapper;
import com.orion.ops.module.infra.enums.RoleStatusEnum;
import com.orion.ops.module.infra.enums.UserStatusEnum;
import org.apache.ibatis.annotations.Mapper;
import java.io.File;
import java.sql.Types;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 代码生成器
*
* @author Jiahang Li
* @version 1.0.0
* @since 2022/4/20 10:33
*/
public class CodeGenerator {
public static void main(String[] args) {
// 输出路径
String outputDir = "D:/MP/";
// 作者
String author = Const.ORION_AUTHOR;
// 模块
String module = "infra";
// 生成的表
GenTable[] tables = {
new GenTable("system_user", "用户", "user")
.vue("user/user", "user", "user")
.enums(UserStatusEnum.class),
new GenTable("system_role", "角色", "role")
.vue("user/role", "user", "role")
.enums(RoleStatusEnum.class),
new GenTable("system_menu", "菜单", "menu"),
};
// jdbc 配置 - 使用配置文件
File yamlFile = new File("orion-ops-launch/src/main/resources/application-dev.yaml");
YmlExt yaml = YmlExt.load(yamlFile);
String url = yaml.getValue("spring.datasource.druid.url");
String username = yaml.getValue("spring.datasource.druid.username");
String password = yaml.getValue("spring.datasource.druid.password");
// 执行
runGenerator(outputDir, author,
url, username, password,
tables, module);
}
/**
* 代码生成
*/
private static void runGenerator(String outputDir,
String author,
String url,
String username,
String password,
GenTable[] tables,
String module) {
// 创建引擎
VelocityTemplateEngine engine = getEngine(tables);
// 获取全局配置
GlobalConfig globalConfig = getGlobalConfig(outputDir, author);
// 数据源配置
DataSourceConfig dataSourceConfig = getDataSourceConfig(url, username, password);
// 策略配置
StrategyConfig strategyConfig = getStrategyConfig(tables);
// 包名配置
PackageConfig packageConfig = getPackageConfig(module);
// 模板配置
TemplateConfig templateConfig = getTemplateConfig();
// 注入配置
InjectionConfig injectionConfig = getInjectionConfig();
// 整合配置
AutoGenerator ag = new AutoGenerator(dataSourceConfig)
// 整合全局配置
.global(globalConfig)
// 整合表名配置
.strategy(strategyConfig)
// 整合包名配置
.packageInfo(packageConfig)
// 整合模板配置
.template(templateConfig)
// 整合注入配置
.injection(injectionConfig);
// 执行
ag.execute(engine);
}
/**
* 获取渲染引擎
*
* @param tables 表
* @return 渲染引擎
*/
private static VelocityTemplateEngine getEngine(GenTable[] tables) {
return new VelocityTemplateEngine(tables);
}
/**
* 获取全局配置
*
* @param outputDir 输出地址
* @param author 作者
* @return config
*/
private static GlobalConfig getGlobalConfig(String outputDir, String author) {
// 全局配置
GlobalConfig gbConfig = new GlobalConfig.Builder()
// 设置作者
.author(author)
// 生成路径
.outputDir(outputDir)
// 生成 spring doc 注解
.enableSpringdoc()
// date类型
.dateType(DateType.ONLY_DATE)
// 注释时间
.commentDate("yyyy-M-d HH:mm")
// 构建
.build();
return gbConfig;
}
/**
* 获取数据源配置
*
* @param url url
* @param username username
* @param password password
* @return 数据源配置
*/
private static DataSourceConfig getDataSourceConfig(String url, String username, String password) {
DataSourceConfig dsConfig = new DataSourceConfig.Builder(url, username, password)
// 转换器
.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
switch (metaInfo.getJdbcType().TYPE_CODE) {
case Types.BIT:
case Types.TINYINT:
return DbColumnType.INTEGER;
default:
return typeRegistry.getColumnType(metaInfo);
}
})
// 查询器
.dbQuery(new MySqlQuery())
// 构建
.build();
return dsConfig;
}
/**
* 获取策略配置
*
* @param tables 生成的表名
* @return 策略配置
*/
private static StrategyConfig getStrategyConfig(GenTable[] tables) {
String[] tableNames = Arrays.stream(tables)
.map(GenTable::getTableName)
.toArray(String[]::new);
StrategyConfig stConfig = new StrategyConfig.Builder()
// 生成的表
.addInclude(tableNames)
// 全局大写命名
.enableCapitalMode()
// 实体配置
.entityBuilder()
// 下滑线转驼峰命名策略
.naming(NamingStrategy.underline_to_camel)
// 实体父类
.superClass(BaseDO.class)
// 实体父类字段
.addSuperEntityColumns("create_time", "update_time", "creator", "updater", "deleted")
// 启用lombok
.enableLombok()
// 主键策略
.idType(IdType.AUTO)
// 添加字段注解
.enableTableFieldAnnotation()
// 实体文件名称
.formatFileName("%sDO")
// 覆盖实体文件
.enableFileOverride()
// mapper 配置
.mapperBuilder()
// dao 添加 @Mapper
.mapperAnnotation(Mapper.class)
// mapper 父类
.superClass(IMapper.class)
// 生成 BaseResultMap
.enableBaseResultMap()
// 生成 BaseColumnList
.enableBaseColumnList()
// mapper 文件名称
.formatMapperFileName("%sDAO")
// xml 文件名称
.formatXmlFileName("%sMapper")
// 覆盖 mapper 文件
.enableFileOverride()
// controller 配置
.controllerBuilder()
// controller 文件名称
.formatFileName("%sController")
// 脊柱命名法
.enableHyphenStyle()
// @RestController
.enableRestStyle()
// 覆盖 controller 文件
.enableFileOverride()
// service 配置
.serviceBuilder()
// 覆盖 service 文件
.enableFileOverride()
// service 名称
.formatServiceFileName("%sService")
// service impl 名称
.formatServiceImplFileName("%sServiceImpl")
// 构建
.build();
return stConfig;
}
/**
* 获取包名配置
*
* @param module 模块
* @return 包名配置
*/
private static PackageConfig getPackageConfig(String module) {
PackageConfig pkConfig = new PackageConfig.Builder()
// 声明父包
.parent("com.orion.ops.module")
// 模块名称
.moduleName(module)
// 实体类的包
.entity("entity.domain")
// 映射接口的包
.mapper("dao")
// 映射文件的包
.xml("mapper")
// service接口的包
.service("service")
// serviceImpl接口的包
.serviceImpl("service.impl")
// controller接口的包
.controller("controller")
// 构建
.build();
return pkConfig;
}
/**
* 获取模板配置
*
* @return 模板配置
*/
private static TemplateConfig getTemplateConfig() {
TemplateConfig tplConfig = new TemplateConfig.Builder()
.controller("/templates/orion-server-controller.java.vm")
.entity("/templates/orion-server-entity-do.java.vm")
.service("/templates/orion-server-service.java.vm")
.serviceImpl("/templates/orion-server-service-impl.java.vm")
.mapper("/templates/orion-server-mapper.java.vm")
.xml("/templates/orion-server-mapper.xml.vm")
.build();
return tplConfig;
}
/**
* 获取注入配置
*
* @return 注入配置
*/
private static InjectionConfig getInjectionConfig() {
String[][] customFileDefineArr = new String[][]{
// http 文件
new String[]{"/templates/orion-server-controller.http.vm", "%sController.http", "controller"},
// vo 文件
new String[]{"/templates/orion-server-entity-vo.java.vm", "%sVO.java", "entity.vo"},
// dto 文件
new String[]{"/templates/orion-server-entity-dto.java.vm", "%sDTO.java", "entity.dto"},
// create request 文件
new String[]{"/templates/orion-server-entity-request-create.java.vm", "%sCreateRequest.java", "entity.request.%s"},
// update request 文件
new String[]{"/templates/orion-server-entity-request-update.java.vm", "%sUpdateRequest.java", "entity.request.%s"},
// query request 文件
new String[]{"/templates/orion-server-entity-request-query.java.vm", "%sQueryRequest.java", "entity.request.%s"},
// convert 文件
new String[]{"/templates/orion-server-convert.java.vm", "%sConvert.java", "convert"},
// convert provider 文件
new String[]{"/templates/orion-server-convert-provider.java.vm", "%sProviderConvert.java", "convert"},
// vue api 文件
new String[]{"/templates/orion-vue-api.ts.vm", "${feature}.ts", "vue/api/${apiPath}"},
// vue views index.ts 文件
new String[]{"/templates/orion-vue-views-index.vue.vm", "index.vue", "vue/views/${viewsPath}"},
// vue form-modal.vue 文件
new String[]{"/templates/orion-vue-views-components-form-modal.vue.vm", "${feature}-form-modal.vue", "vue/views/${viewsPath}/components"},
// vue table.vue 文件
new String[]{"/templates/orion-vue-views-components-table.vue.vm", "${feature}-table.vue", "vue/views/${viewsPath}/components"},
// vue enum.types.ts 文件
new String[]{"/templates/orion-vue-views-types-enum.types.ts.vm", "enum.types.ts", "vue/views/${viewsPath}/types"},
// vue form.rules.ts 文件
new String[]{"/templates/orion-vue-views-types-form.rules.ts.vm", "form.rules.ts", "vue/views/${viewsPath}/types"},
// vue table.vue 文件
new String[]{"/templates/orion-vue-views-types-table.columns.ts.vm", "table.columns.ts", "vue/views/${viewsPath}/types"},
};
// 构建文件
List<CustomFile> customerFiles = Arrays.stream(customFileDefineArr)
.map(s -> {
return new CustomFile.Builder()
// 覆盖文件
.enableFileOverride()
// 模板路径
.templatePath(s[0])
// 文件名
.fileName(s[1])
// 包名
.packageName(s[2])
.build();
}).collect(Collectors.toList());
// 注入配置
InjectionConfig injection = new InjectionConfig.Builder()
// 自定义 文件
.customFile(customerFiles)
// 构建
.build();
return injection;
}
}

View File

@@ -0,0 +1,96 @@
package com.orion.ops.launch.generator;
import com.orion.lang.utils.collect.Lists;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* @author Jiahang Li
* @version 1.0.0
* @since 2023/7/17 10:44
*/
@Data
public class GenTable {
// -------------------- 后端 --------------------
/**
* 表名称
*/
private String tableName;
/**
* 业务注释
*/
private String comment;
/**
* 请求实体包名
*/
private String requestPackage;
// -------------------- 前端 --------------------
/**
* 是否生成 vue 代码
*/
private boolean genVue;
/**
* views 父目录
*/
private String viewsPath;
/**
* api 文件目录
*/
private String apiPath;
/**
* 功能 用于文件名称生成
*/
private String feature;
/**
* 生成的枚举文件
*/
private List<Class<? extends Enum<?>>> enums;
public GenTable(String tableName, String comment, String requestPackage) {
this.tableName = tableName;
this.comment = comment;
this.requestPackage = requestPackage;
this.enums = new ArrayList<>();
}
/**
* 生成 vue 模板
*
* @param viewsPath viewsPath
* @param apiPath apiPath
* @param feature feature
* @return this
*/
public GenTable vue(String viewsPath, String apiPath, String feature) {
this.genVue = true;
this.viewsPath = viewsPath;
this.apiPath = apiPath;
this.feature = feature;
return this;
}
/**
* 生成 vue 枚举对象
*
* @param enums enums
* @return enums
*/
@SafeVarargs
public final GenTable enums(Class<? extends Enum<?>>... enums) {
this.enums.addAll(Lists.of(enums));
return this;
}
}

View File

@@ -0,0 +1,279 @@
/*
* Copyright (c) 2011-2022, baomidou (jobob@qq.com).
*
* 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 com.orion.ops.launch.generator;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.config.ConstVal;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
import com.orion.lang.utils.Strings;
import com.orion.lang.utils.io.Files1;
import com.orion.lang.utils.reflect.BeanMap;
import com.orion.lang.utils.reflect.Fields;
import com.orion.ops.framework.common.constant.OrionOpsProConst;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 代码生成器 Velocity 引擎
*
* @author Jiahang Li
* @version 1.0.0
* @since 2022/4/20 10:33
*/
public class VelocityTemplateEngine extends AbstractTemplateEngine {
private static final String REQUEST_PACKAGE_REPLACER = "request.%s";
private final Map<String, GenTable> tables;
private VelocityEngine velocityEngine;
public VelocityTemplateEngine(GenTable[] tables) {
this.tables = Arrays.stream(tables)
.collect(Collectors.toMap(GenTable::getTableName, Function.identity()));
}
{
try {
Class.forName("org.apache.velocity.util.DuckType");
} catch (ClassNotFoundException e) {
LOGGER.warn("Velocity 1.x is outdated, please upgrade to 2.x or later.");
}
}
@Override
@NotNull
public VelocityTemplateEngine init(@NotNull ConfigBuilder configBuilder) {
if (velocityEngine == null) {
Properties p = new Properties();
p.setProperty(ConstVal.VM_LOAD_PATH_KEY, ConstVal.VM_LOAD_PATH_VALUE);
p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, StringPool.EMPTY);
p.setProperty(Velocity.ENCODING_DEFAULT, ConstVal.UTF8);
p.setProperty(Velocity.INPUT_ENCODING, ConstVal.UTF8);
p.setProperty("file.resource.loader.unicode", StringPool.TRUE);
velocityEngine = new VelocityEngine(p);
}
return this;
}
@Override
public void writer(@NotNull Map<String, Object> objectMap, @NotNull String templatePath, @NotNull File outputFile) throws Exception {
Template template = velocityEngine.getTemplate(templatePath, ConstVal.UTF8);
try (FileOutputStream fos = new FileOutputStream(outputFile);
OutputStreamWriter ow = new OutputStreamWriter(fos, ConstVal.UTF8);
BufferedWriter writer = new BufferedWriter(ow)) {
template.merge(new VelocityContext(objectMap), writer);
}
LOGGER.debug("模板:" + templatePath + "; 文件:" + outputFile);
}
@Override
@NotNull
public String templateFilePath(@NotNull String filePath) {
final String dotVm = ".vm";
return filePath.endsWith(dotVm) ? filePath : filePath + dotVm;
}
/**
* 创建自定义文件副本对象
*
* @param originCustomerFile originCustomerFile
* @return backup
*/
private List<CustomFile> createCustomFilesBackup(@NotNull List<CustomFile> originCustomerFile) {
// 生成文件副本
List<CustomFile> customFiles = originCustomerFile.stream().map(s -> {
return new CustomFile.Builder()
.enableFileOverride()
.templatePath(s.getTemplatePath())
.filePath(s.getFilePath())
.fileName(s.getFileName())
.packageName(s.getPackageName())
.build();
}).collect(Collectors.toList());
return customFiles;
}
/**
* 替换自定义文件包
*
* @param customFiles 自定义文件
* @param tableInfo tableInfo
* @param objectMap objectMap
*/
private void replacePackageName(@NotNull List<CustomFile> customFiles, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
// 替换包名
customFiles.forEach(s -> {
// 反射调用 setter 方法
BiConsumer<String, Object> callSetter = (field, value) -> Fields.setFieldValue(s, field, value);
String packageName = s.getPackageName();
// 替换 Request.java 文件包名
if (packageName.contains(REQUEST_PACKAGE_REPLACER)) {
String replacePackage = String.format(packageName, tables.get(tableInfo.getName()).getRequestPackage());
callSetter.accept("packageName", replacePackage);
}
});
// 自定义文件的包 (导入用)
List<String> customFilePackages = customFiles.stream()
.filter(s -> s.getTemplatePath().contains(".java.vm"))
.map(CustomFile::getPackageName)
.map(s -> getConfigBuilder().getPackageConfig().getParent() + "." + s)
.distinct()
.collect(Collectors.toList());
objectMap.put("customFilePackages", customFilePackages);
}
/**
* 插入表元数据
*
* @param tableInfo tableInfo
* @param objectMap objectMap
*/
private void addTableMeta(@NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
// http 注释标识
objectMap.put("httpComment", "###");
// 版本
objectMap.put("since", OrionOpsProConst.VERSION);
// 替换业务注释
tableInfo.setComment(tables.get(tableInfo.getName()).getComment());
// 实体名称
String domainName = tableInfo.getEntityName();
String mappingHyphen = objectMap.get("controllerMappingHyphen").toString();
String entityName = domainName.substring(0, domainName.length() - 2);
objectMap.put("type", entityName);
objectMap.put("typeLower", Strings.firstLower(entityName));
objectMap.put("typeHyphen", mappingHyphen.substring(0, mappingHyphen.length() - 3));
}
/**
* 插入 api 注释
*
* @param tableInfo tableInfo
* @param objectMap objectMap
*/
private void addApiCommentMeta(@NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
Map<String, String> map = new HashMap<>();
objectMap.put("apiComment", map);
String comment = tableInfo.getComment();
map.put("create", "创建" + comment);
map.put("update", "通过 id 更新" + comment);
map.put("get", "通过 id 查询" + comment);
map.put("list", "通过 id 批量查询" + comment);
map.put("query", "分页查询" + comment);
map.put("delete", "通过 id 删除" + comment);
map.put("batchDelete", "通过 id 批量删除" + comment);
}
@Override
protected void outputCustomFile(@NotNull List<CustomFile> customFiles, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
// 创建自定义文件副本文件
customFiles = this.createCustomFilesBackup(customFiles);
// 替换自定义包名
this.replacePackageName(customFiles, tableInfo, objectMap);
// 添加表元数据
this.addTableMeta(tableInfo, objectMap);
// 添加注释元数据
this.addApiCommentMeta(tableInfo, objectMap);
// 生成后端文件
List<CustomFile> serverFiles = customFiles.stream()
.filter(s -> !this.isVueFile(s.getTemplatePath()))
.collect(Collectors.toList());
this.generatorServerFile(serverFiles, tableInfo, objectMap);
// 生成前端文件
if (tables.get(tableInfo.getName()).isGenVue()) {
List<CustomFile> vueFiles = customFiles.stream()
.filter(s -> this.isVueFile(s.getTemplatePath()))
.collect(Collectors.toList());
this.generatorVueFile(vueFiles, tableInfo, objectMap);
}
}
/**
* 生成后端文件
*
* @param customFiles customFiles
* @param tableInfo tableInfo
* @param objectMap objectMap
*/
private void generatorServerFile(@NotNull List<CustomFile> customFiles, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
String parentPath = getPathInfo(OutputFile.parent);
// 生成文件
customFiles.forEach(file -> {
// 获取 parent package
String currentPackage = getConfigBuilder().getPackageConfig().getParent() + "." + file.getPackageName();
// 设置当前包
objectMap.put("currentPackage", currentPackage);
// 文件路径
String filePath = parentPath + File.separator + file.getPackageName()
.replaceAll("\\.", StringPool.BACK_SLASH + File.separator);
String fileName = filePath + File.separator + String.format(file.getFileName(), objectMap.get("type"));
outputFile(Files1.newFile(fileName), objectMap, file.getTemplatePath(), file.isFileOverride());
});
}
/**
* 生成前端文件
*
* @param customFiles customFiles
* @param tableInfo tableInfo
* @param objectMap objectMap
*/
private void generatorVueFile(@NotNull List<CustomFile> customFiles, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
String outPath = getConfigBuilder().getGlobalConfig().getOutputDir();
GenTable table = tables.get(tableInfo.getName());
BeanMap beanMap = BeanMap.create(table, "enums");
// 生成文件
customFiles.forEach(file -> {
// 文件路径
String filePath = outPath
+ "/" + Strings.format(file.getPackageName(), beanMap)
+ "/" + Strings.format(file.getFileName(), beanMap);
// 输出文件
this.outputFile(Files1.newFile(filePath), objectMap, file.getTemplatePath(), file.isFileOverride());
});
}
/**
* 是否为 vue 文件
*
* @param templatePath templatePath
* @return 是否为 vue 文件
*/
private boolean isVueFile(String templatePath) {
return templatePath.endsWith(".ts.vm") ||
templatePath.endsWith(".vue.vm");
}
}

View File

@@ -0,0 +1,61 @@
${httpComment} ${apiComment.create}
POST {{baseUrl}}/${package.ModuleName}/${typeHyphen}/create
Content-Type: application/json
Authorization: {{token}}
{
#foreach($field in ${table.fields})
#if("$!field.propertyName" != "id")
"${field.propertyName}": ""#if($foreach.hasNext),#end
#end
#end
}
${httpComment} ${apiComment.update}
PUT {{baseUrl}}/${package.ModuleName}/${typeHyphen}/update
Content-Type: application/json
Authorization: {{token}}
{
#foreach($field in ${table.fields})
"${field.propertyName}": ""#if($foreach.hasNext),#end
#end
}
${httpComment} ${apiComment.get}
GET {{baseUrl}}/${package.ModuleName}/${typeHyphen}/get?id=1
Authorization: {{token}}
${httpComment} ${apiComment.list}
GET {{baseUrl}}/${package.ModuleName}/${typeHyphen}/list?idList=1,2,3
Authorization: {{token}}
${httpComment} ${apiComment.query}
POST {{baseUrl}}/${package.ModuleName}/${typeHyphen}/query
Content-Type: application/json
Authorization: {{token}}
{
#foreach($field in ${table.fields})
"${field.propertyName}": ""#if($foreach.hasNext),#end
#end
}
${httpComment} ${apiComment.delete}
DELETE {{baseUrl}}/${package.ModuleName}/${typeHyphen}/delete?id=1
Authorization: {{token}}
${httpComment} ${apiComment.batchDelete}
DELETE {{baseUrl}}/${package.ModuleName}/${typeHyphen}/delete-batch?idList=1,2,3
Authorization: {{token}}
${httpComment}

View File

@@ -0,0 +1,105 @@
package ${package.Controller};
import com.orion.lang.define.wrapper.DataGrid;
import com.orion.ops.framework.common.annotation.IgnoreLog;
import com.orion.ops.framework.common.annotation.RestWrapper;
import com.orion.ops.framework.common.constant.IgnoreLogMode;
import ${package.Service}.*;
#foreach($pkg in ${customFilePackages})
import ${pkg}.*;
#end
#if(${superControllerClassPackage})
import ${superControllerClassPackage};
#end
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* $!{table.comment} api
*
* @author ${author}
* @version ${since}
* @since ${date}
*/
@Tag(name = "${package.ModuleName} - $!{table.comment}服务")
@Slf4j
@Validated
@RestWrapper
@RestController
@RequestMapping("/${package.ModuleName}/${typeHyphen}")
@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"})
#if(${superControllerClass})
public class ${table.controllerName} extends ${superControllerClass} {
#else
public class ${table.controllerName} {
#end
@Resource
private ${type}Service ${typeLower}Service;
@PostMapping("/create")
@Operation(summary = "${apiComment.create}")
@PreAuthorize("@ss.hasPermission('${package.ModuleName}:${typeHyphen}:create')")
public Long create${type}(@Validated @RequestBody ${type}CreateRequest request) {
return ${typeLower}Service.create${type}(request);
}
@PutMapping("/update")
@Operation(summary = "${apiComment.update}")
@PreAuthorize("@ss.hasPermission('${package.ModuleName}:${typeHyphen}:update')")
public Integer update${type}(@Validated @RequestBody ${type}UpdateRequest request) {
return ${typeLower}Service.update${type}(request);
}
@IgnoreLog(IgnoreLogMode.RET)
@GetMapping("/get")
@Operation(summary = "${apiComment.get}")
@Parameter(name = "id", description = "id", required = true)
@PreAuthorize("@ss.hasPermission('${package.ModuleName}:${typeHyphen}:query')")
public ${type}VO get${type}(@RequestParam("id") Long id) {
return ${typeLower}Service.get${type}(id);
}
@IgnoreLog(IgnoreLogMode.RET)
@GetMapping("/list")
@Operation(summary = "${apiComment.list}")
@Parameter(name = "idList", description = "idList", required = true)
@PreAuthorize("@ss.hasPermission('${package.ModuleName}:${typeHyphen}:query')")
public List<${type}VO> get${type}List(@RequestParam("idList") List<Long> idList) {
return ${typeLower}Service.get${type}List(idList);
}
@IgnoreLog(IgnoreLogMode.RET)
@PostMapping("/query")
@Operation(summary = "${apiComment.query}")
@PreAuthorize("@ss.hasPermission('${package.ModuleName}:${typeHyphen}:query')")
public DataGrid<${type}VO> get${type}Page(@Validated @RequestBody ${type}QueryRequest request) {
return ${typeLower}Service.get${type}Page(request);
}
@DeleteMapping("/delete")
@Operation(summary = "${apiComment.delete}")
@Parameter(name = "id", description = "id", required = true)
@PreAuthorize("@ss.hasPermission('${package.ModuleName}:${typeHyphen}:delete')")
public Integer delete${type}(@RequestParam("id") Long id) {
return ${typeLower}Service.delete${type}(id);
}
@DeleteMapping("/delete-batch")
@Operation(summary = "${apiComment.batchDelete}")
@Parameter(name = "idList", description = "idList", required = true)
@PreAuthorize("@ss.hasPermission('${package.ModuleName}:${typeHyphen}:delete')")
public Integer batchDelete${type}(@RequestParam("idList") List<Long> idList) {
return ${typeLower}Service.batchDelete${type}(idList);
}
}

View File

@@ -0,0 +1,31 @@
package ${currentPackage};
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import ${package.Entity}.*;
#foreach($pkg in ${customFilePackages})
import ${pkg}.*;
#end
import java.util.List;
/**
* $!{table.comment} 暴露服务转换器
*
* @author ${author}
* @version ${since}
* @since ${date}
*/
@Mapper
public interface ${type}ProviderConvert {
${type}ProviderConvert MAPPER = Mappers.getMapper(${type}ProviderConvert.class);
${type}DO to(${type}DTO dto);
${type}DTO to(${type}DO domain);
List<${type}DO> toDO(List<${type}DTO> list);
List<${type}DTO> toDTO(List<${type}DO> list);
}

View File

@@ -0,0 +1,33 @@
package ${currentPackage};
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import ${package.Entity}.*;
#foreach($pkg in ${customFilePackages})
import ${pkg}.*;
#end
import java.util.List;
/**
* $!{table.comment} 内部对象转换器
*
* @author ${author}
* @version ${since}
* @since ${date}
*/
@Mapper
public interface ${type}Convert {
${type}Convert MAPPER = Mappers.getMapper(${type}Convert.class);
${type}DO to(${type}CreateRequest request);
${type}DO to(${type}UpdateRequest request);
${type}DO to(${type}QueryRequest request);
${type}VO to(${type}DO domain);
List<${type}VO> to(List<${type}DO> list);
}

View File

@@ -0,0 +1,77 @@
package ${package.Entity};
import com.baomidou.mybatisplus.annotation.*;
import com.orion.ops.framework.mybatis.core.domain.BaseDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
/**
* $!{table.comment} 实体对象
*
* @author ${author}
* @version ${since}
* @since ${date}
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
#if(${table.convert})
@TableName(value = "${schemaName}${table.name}", autoResultMap = true)
#end
@Schema(name = "${entity}", description = "$!{table.comment} 实体对象")
#if(${superEntityClass})
public class ${entity} extends ${superEntityClass}#if(${activeRecord})<${entity}>#end {
#elseif(${entitySerialVersionUID})
public class ${entity} implements Serializable {
#else
public class ${entity} {
#end
#if(${entitySerialVersionUID})
private static final long serialVersionUID = 1L;
#end
## ---------- BEGIN 字段循环遍历 ----------
#foreach($field in ${table.fields})
#if(${field.keyFlag})
#set($keyPropertyName=${field.propertyName})
#end
#if("$!field.comment" != "")
@Schema(description = "${field.comment}")
#end
#if(${field.keyFlag})
## 主键
#if(${field.keyIdentityFlag})
@TableId(value = "${field.annotationColumnName}", type = IdType.AUTO)
#elseif(!$null.isNull(${idType}) && "$!idType" != "")
@TableId(value = "${field.annotationColumnName}", type = IdType.${idType})
#elseif(${field.convert})
@TableId("${field.annotationColumnName}")
#end
## 普通字段
#elseif(${field.fill})
## ----- 存在字段填充设置 -----
#if(${field.convert})
@TableField(value = "${field.annotationColumnName}", fill = FieldFill.${field.fill})
#else
@TableField(fill = FieldFill.${field.fill})
#end
#elseif(${field.convert})
@TableField("${field.annotationColumnName}")
#end
## 乐观锁注解
#if(${field.versionField})
@Version
#end
## 逻辑删除注解
#if(${field.logicDeleteField})
@TableLogic
#end
private ${field.propertyType} ${field.propertyName};
#end
}

View File

@@ -0,0 +1,44 @@
package ${currentPackage};
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serializable;
import lombok.*;
import java.util.*;
/**
* $!{table.comment} 业务对象
*
* @author ${author}
* @version ${since}
* @since ${date}
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "${type}DTO", description = "$!{table.comment} 业务对象")
public class ${type}DTO implements Serializable {
private static final long serialVersionUID = 1L;
#foreach($field in ${table.fields})
#if("$!field.comment" != "")
@Schema(description = "${field.comment}")
#end
private ${field.propertyType} ${field.propertyName};
#end
@Schema(description = "创建时间")
private Date createTime;
@Schema(description = "修改时间")
private Date updateTime;
@Schema(description = "创建人")
private String creator;
@Schema(description = "修改人")
private String updater;
}

View File

@@ -0,0 +1,44 @@
package ${currentPackage};
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.*;
/**
* $!{table.comment} 创建请求对象
*
* @author ${author}
* @version ${since}
* @since ${date}
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "${type}CreateRequest", description = "$!{table.comment} 创建请求对象")
public class ${type}CreateRequest implements Serializable {
#foreach($field in ${table.fields})
#if("$!field.propertyName" != "id")
#if("$field.propertyType" == "String")
@NotBlank
@Size(max = $field.metaInfo.length)
#else
@NotNull
#end
#if("$!field.comment" != "")
@Schema(description = "${field.comment}")
#end
private ${field.propertyType} ${field.propertyName};
#end
#end
}

View File

@@ -0,0 +1,35 @@
package ${currentPackage};
import com.orion.ops.framework.common.entity.PageRequest;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import javax.validation.constraints.Size;
import java.util.*;
/**
* $!{table.comment} 查询请求对象
*
* @author ${author}
* @version ${since}
* @since ${date}
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Schema(name = "${type}QueryRequest", description = "$!{table.comment} 查询请求对象")
public class ${type}QueryRequest extends PageRequest {
#foreach($field in ${table.fields})
#if("$field.propertyType" == "String")
@Size(max = $field.metaInfo.length)
#end
#if("$!field.comment" != "")
@Schema(description = "${field.comment}")
#end
private ${field.propertyType} ${field.propertyName};
#end
}

View File

@@ -0,0 +1,42 @@
package ${currentPackage};
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.*;
/**
* $!{table.comment} 更新请求对象
*
* @author ${author}
* @version ${since}
* @since ${date}
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "${type}UpdateRequest", description = "$!{table.comment} 更新请求对象")
public class ${type}UpdateRequest implements Serializable {
#foreach($field in ${table.fields})
#if("$field.propertyType" == "String")
@NotBlank
@Size(max = $field.metaInfo.length)
#else
@NotNull
#end
#if("$!field.comment" != "")
@Schema(description = "${field.comment}")
#end
private ${field.propertyType} ${field.propertyName};
#end
}

View File

@@ -0,0 +1,44 @@
package ${currentPackage};
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serializable;
import lombok.*;
import java.util.*;
/**
* $!{table.comment} 视图响应对象
*
* @author ${author}
* @version ${since}
* @since ${date}
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "${type}VO", description = "$!{table.comment} 视图响应对象")
public class ${type}VO implements Serializable {
private static final long serialVersionUID = 1L;
#foreach($field in ${table.fields})
#if("$!field.comment" != "")
@Schema(description = "${field.comment}")
#end
private ${field.propertyType} ${field.propertyName};
#end
@Schema(description = "创建时间")
private Date createTime;
@Schema(description = "修改时间")
private Date updateTime;
@Schema(description = "创建人")
private String creator;
@Schema(description = "修改人")
private String updater;
}

View File

@@ -0,0 +1,35 @@
package ${package.Mapper};
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import ${package.Entity}.${entity};
import ${superMapperClassPackage};
#if(${mapperAnnotationClass})
import ${mapperAnnotationClass.name};
#end
/**
* $!{table.comment} Mapper 接口
*
* @author ${author}
* @version ${since}
* @since ${date}
*/
#if(${mapperAnnotationClass})
@${mapperAnnotationClass.simpleName}
#end
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {
/**
* 获取全部条件
*
* @param entity entity
* @return 全部条件
*/
default LambdaQueryWrapper<${entity}> condition(${entity} entity) {
return this.wrapper()
#foreach($field in ${table.fields})
.eq(${type}DO::get${field.capitalName}, entity.get${field.capitalName}())#if(!$foreach.hasNext);#end
#end
}
}

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${package.Mapper}.${table.mapperName}">
#if(${enableCache})
<!-- 开启二级缓存 -->
<cache type="${cacheClassName}"/>
#end
#if(${baseResultMap})
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="${package.Entity}.${entity}">
#foreach($field in ${table.fields})
#if(${field.keyFlag})##生成主键排在第一位
<id column="${field.name}" property="${field.propertyName}"/>
#end
#end
#foreach($field in ${table.commonFields})##生成公共字段
<result column="${field.name}" property="${field.propertyName}"/>
#end
#foreach($field in ${table.fields})
#if(!${field.keyFlag})##生成普通字段
<result column="${field.name}" property="${field.propertyName}"/>
#end
#end
</resultMap>
#end
#if(${baseColumnList})
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
#foreach($field in ${table.commonFields})#if(${foreach.count} == 1) #end${field.columnName}, #end${table.fieldNames}
</sql>
#end
</mapper>

View File

@@ -0,0 +1,134 @@
package ${package.ServiceImpl};
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.orion.lang.define.wrapper.DataGrid;
import com.orion.lang.utils.collect.Lists;
import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.utils.Valid;
#foreach($pkg in ${customFilePackages})
import ${pkg}.*;
#end
import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${package.Service}.${table.serviceName};
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* $!{table.comment} 服务实现类
*
* @author ${author}
* @version ${since}
* @since ${date}
*/
@Slf4j
@Service
public class ${table.serviceImplName} implements ${table.serviceName} {
@Resource
private ${type}DAO ${typeLower}DAO;
@Override
public Long create${type}(${type}CreateRequest request) {
// 转换
${type}DO record = ${type}Convert.MAPPER.to(request);
record.setId(null);
// 查询数据是否冲突
this.check${type}Present(record);
// 插入
int effect = ${typeLower}DAO.insert(record);
log.info("${type}Service-create${type} effect: {}, record: {}", effect, JSON.toJSONString(record));
return record.getId();
}
@Override
public Integer update${type}(${type}UpdateRequest request) {
// 查询
Long id = Valid.notNull(request.getId(), ErrorMessage.ID_MISSING);
${type}DO record = ${typeLower}DAO.selectById(id);
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
// 转换
${type}DO updateRecord = ${type}Convert.MAPPER.to(request);
// 查询数据是否冲突
this.check${type}Present(updateRecord);
// 更新
int effect = ${typeLower}DAO.updateById(updateRecord);
log.info("${type}Service-update${type} effect: {}, updateRecord: {}", effect, JSON.toJSONString(updateRecord));
return effect;
}
@Override
public ${type}VO get${type}(Long id) {
// 查询
${type}DO record = ${typeLower}DAO.selectById(id);
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
// 转换
return ${type}Convert.MAPPER.to(record);
}
@Override
public List<${type}VO> get${type}List(List<Long> idList) {
// 查询
List<${type}DO> records = ${typeLower}DAO.selectBatchIds(idList);
if (records.isEmpty()) {
return Lists.empty();
}
// 转换
return ${type}Convert.MAPPER.to(records);
}
@Override
public DataGrid<${type}VO> get${type}Page(${type}QueryRequest request) {
// 构造条件
LambdaQueryWrapper<${type}DO> wrapper = ${typeLower}DAO.wrapper()
#foreach($field in ${table.fields})
.eq(${type}DO::get${field.capitalName}, request.get${field.capitalName}())
#end
.orderByDesc(${type}DO::getId);
// 查询
return ${typeLower}DAO.of()
.wrapper(wrapper)
.page(request)
.dataGrid(${type}Convert.MAPPER::to);
}
@Override
public Integer delete${type}(Long id) {
int effect = ${typeLower}DAO.deleteById(id);
log.info("${type}Service-delete${type} id: {}, effect: {}", id, effect);
return effect;
}
@Override
public Integer batchDelete${type}(List<Long> idList) {
int effect = ${typeLower}DAO.deleteBatchIds(idList);
log.info("${type}Service-batchDelete${type} idList: {}, effect: {}", JSON.toJSONString(idList), effect);
return effect;
}
/**
* 检测对象是否存在
*
* @param domain domain
*/
private void check${type}Present(${type}DO domain) {
// 构造条件
LambdaQueryWrapper<${type}DO> wrapper = ${typeLower}DAO.wrapper()
// 更新时忽略当前记录
.ne(${type}DO::getId, domain.getId())
// 用其他字段做重复校验
#foreach($field in ${table.fields})
#if("$!field.propertyName" != "id")
.eq(${type}DO::get${field.capitalName}, domain.get${field.capitalName}())#if(!$foreach.hasNext);#end
#end
#end
// 检查是否存在
boolean present = ${typeLower}DAO.of().wrapper(wrapper).present();
Valid.isFalse(present, ErrorMessage.DATA_PRESENT);
}
}

View File

@@ -0,0 +1,75 @@
package ${package.Service};
import com.orion.lang.define.wrapper.DataGrid;
#foreach($pkg in ${customFilePackages})
import ${pkg}.*;
#end
import java.util.List;
/**
* $!{table.comment} 服务类
*
* @author ${author}
* @version ${since}
* @since ${date}
*/
public interface ${table.serviceName} {
/**
* ${apiComment.create}
*
* @param request request
* @return id
*/
Long create${type}(${type}CreateRequest request);
/**
* ${apiComment.update}
*
* @param request request
* @return effect
*/
Integer update${type}(${type}UpdateRequest request);
/**
* ${apiComment.get}
*
* @param id id
* @return row
*/
${type}VO get${type}(Long id);
/**
* ${apiComment.list}
*
* @param idList idList
* @return rows
*/
List<${type}VO> get${type}List(List<Long> idList);
/**
* ${apiComment.query}
*
* @param request request
* @return rows
*/
DataGrid<${type}VO> get${type}Page(${type}QueryRequest request);
/**
* ${apiComment.delete}
*
* @param id id
* @return effect
*/
Integer delete${type}(Long id);
/**
* ${apiComment.batchDelete}
*
* @param idList idList
* @return effect
*/
Integer batchDelete${type}(List<Long> idList);
}

View File

@@ -0,0 +1 @@
api

View File

@@ -0,0 +1 @@
orion-vue-views-types-form.rules.ts

View File

@@ -0,0 +1 @@
orion-vue-views-types-table.columns.ts.vm