Skip to content

Commit

Permalink
!65 新增主子表、树表的代码生成
Browse files Browse the repository at this point in the history
Merge pull request !65 from 芋道源码/feature/vo-optimize
  • Loading branch information
YunaiV authored and gitee-org committed Nov 18, 2023
2 parents 95d5fc4 + a6edd13 commit c8c0c84
Show file tree
Hide file tree
Showing 242 changed files with 13,657 additions and 1,713 deletions.
265 changes: 202 additions & 63 deletions sql/mysql/ruoyi-vue-pro.sql

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ public class PageParam implements Serializable {
private static final Integer PAGE_NO = 1;
private static final Integer PAGE_SIZE = 10;

/**
* 每页条数 - 不分页
*
* 例如说,导出接口,可以设置 {@link #pageSize} 为 -1 不分页,查询所有数据。
*/
public static final Integer PAGE_SIZE_NONE = -1;

@Schema(description = "页码,从 1 开始", requiredMode = Schema.RequiredMode.REQUIRED,example = "1")
@NotNull(message = "页码不能为空")
@Min(value = 1, message = "页码最小值为 1")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ public static <T, V extends Comparable<? super V>> V getMaxValue(Collection<T> f
if (CollUtil.isEmpty(from)) {
return null;
}
assert from.size() > 0; // 断言,避免告警
assert !from.isEmpty(); // 断言,避免告警
T t = from.stream().max(Comparator.comparing(valueFunc)).get();
return valueFunc.apply(t);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
Expand Down Expand Up @@ -30,6 +31,7 @@ public class JsonUtils {
static {
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略 null 值
objectMapper.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化
}

Expand Down Expand Up @@ -71,6 +73,20 @@ public static <T> T parseObject(String text, Class<T> clazz) {
}
}

public static <T> T parseObject(String text, String path, Class<T> clazz) {
if (StrUtil.isEmpty(text)) {
return null;
}
try {
JsonNode treeNode = objectMapper.readTree(text);
JsonNode pathNode = treeNode.path(path);
return objectMapper.readValue(pathNode.toString(), clazz);
} catch (IOException e) {
log.error("json parse err,json:{}", text, e);
throw new RuntimeException(e);
}
}

public static <T> T parseObject(String text, Type type) {
if (StrUtil.isEmpty(text)) {
return null;
Expand Down Expand Up @@ -132,6 +148,20 @@ public static <T> List<T> parseArray(String text, Class<T> clazz) {
}
}

public static <T> List<T> parseArray(String text, String path, Class<T> clazz) {
if (StrUtil.isEmpty(text)) {
return null;
}
try {
JsonNode treeNode = objectMapper.readTree(text);
JsonNode pathNode = treeNode.path(path);
return objectMapper.readValue(pathNode.toString(), objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
} catch (IOException e) {
log.error("json parse err,json:{}", text, e);
throw new RuntimeException(e);
}
}

public static JsonNode parseTree(String text) {
try {
return objectMapper.readTree(text);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package cn.iocoder.yudao.framework.common.util.object;

import cn.hutool.core.bean.BeanUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;

import java.util.List;

/**
* Bean 工具类
*
* 1. 默认使用 {@link cn.hutool.core.bean.BeanUtil} 作为实现类,虽然不同 bean 工具的性能有差别,但是对绝大多数同学的项目,不用在意这点性能
* 2. 针对复杂的对象转换,可以搜参考 AuthConvert 实现,通过 mapstruct + default 配合实现
*
* @author 芋道源码
*/
public class BeanUtils {

public static <T> T toBean(Object source, Class<T> targetClass) {
return BeanUtil.toBean(source, targetClass);
}

public static <S, T> List<T> toBean(List<S> source, Class<T> targetType) {
if (source == null) {
return null;
}
return CollectionUtils.convertList(source, s -> toBean(s, targetType));
}

public static <S, T> PageResult<T> toBean(PageResult<S> source, Class<T> targetType) {
if (source == null) {
return null;
}
return new PageResult<>(toBean(source.getList(), targetType), source.getTotal());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,20 @@ public static List<Integer> splitToInteger(String value, CharSequence separator)
return Arrays.stream(integers).boxed().collect(Collectors.toList());
}

/**
* 移除字符串中,包含指定字符串的行
*
* @param content 字符串
* @param sequence 包含的字符串
* @return 移除后的字符串
*/
public static String removeLineContains(String content, String sequence) {
if (StrUtil.isEmpty(content) || StrUtil.isEmpty(sequence)) {
return content;
}
return Arrays.stream(content.split("\n"))
.filter(line -> !line.contains(sequence))
.collect(Collectors.joining("\n"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
public interface BaseMapperX<T> extends MPJBaseMapper<T> {

default PageResult<T> selectPage(PageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
// 特殊:不分页,直接查询全部
if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageNo())) {
List<T> list = selectList(queryWrapper);
return new PageResult<>(list, (long) list.size());
}

// MyBatis Plus 查询
IPage<T> mpPage = MyBatisUtils.buildPage(pageParam);
selectPage(mpPage, queryWrapper);
Expand Down Expand Up @@ -93,10 +99,15 @@ default List<T> selectList(SFunction<T, ?> field, Collection<?> values) {
return selectList(new LambdaQueryWrapper<T>().in(field, values));
}

@Deprecated
default List<T> selectList(SFunction<T, ?> leField, SFunction<T, ?> geField, Object value) {
return selectList(new LambdaQueryWrapper<T>().le(leField, value).ge(geField, value));
}

default List<T> selectList(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
return selectList(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
}

/**
* 批量插入,适合大量数据插入
*
Expand Down Expand Up @@ -128,8 +139,20 @@ default void updateBatch(Collection<T> entities, int size) {
Db.updateBatchById(entities, size);
}

default void saveOrUpdateBatch(Collection<T> collection) {
default void insertOrUpdate(T entity) {
Db.saveOrUpdate(entity);
}

default void insertOrUpdateBatch(Collection<T> collection) {
Db.saveOrUpdateBatch(collection);
}

default int delete(String field, String value) {
return delete(new QueryWrapper<T>().eq(field, value));
}

default int delete(SFunction<T, ?> field, Object value) {
return delete(new LambdaQueryWrapper<T>().eq(field, value));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ public interface ErrorCodeConstants {
ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1_003_001_007, "同步失败,不存在改变");
ErrorCode CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL = new ErrorCode(1_003_001_008, "数据库的表注释未填写");
ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1_003_001_009, "数据库的表字段({})注释未填写");

// ========== 字典类型(测试)1-001-005-000 ==========
ErrorCode TEST_DEMO_NOT_EXISTS = new ErrorCode(1_001_005_000, "测试示例不存在");
ErrorCode CODEGEN_MASTER_TABLE_NOT_EXISTS = new ErrorCode(1_003_001_010, "主表(id={})定义不存在,请检查");
ErrorCode CODEGEN_SUB_COLUMN_NOT_EXISTS = new ErrorCode(1_003_001_011, "子表的字段(id={})不存在,请检查");
ErrorCode CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_TABLE = new ErrorCode(1_003_001_012, "主表生成代码失败,原因:它没有子表");
ErrorCode CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_COLUMN = new ErrorCode(1_003_001_013, "主表生成代码失败,原因:它的子表({})没有字段");

// ========== 文件配置 1-001-006-000 ==========
ErrorCode FILE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_006_000, "文件配置不存在");
Expand All @@ -54,4 +55,19 @@ public interface ErrorCodeConstants {
ErrorCode DATA_SOURCE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_007_000, "数据源配置不存在");
ErrorCode DATA_SOURCE_CONFIG_NOT_OK = new ErrorCode(1_001_007_001, "数据源配置不正确,无法进行连接");

// ========== 数据源配置 1-001-107-000 ==========
ErrorCode DEMO_STUDENT_NOT_EXISTS = new ErrorCode(1_001_107_000, "学生不存在");

// ========== 学生 1-001-201-000 ==========
ErrorCode DEMO01_CONTACT_NOT_EXISTS = new ErrorCode(1_001_201_000, "示例联系人不存在");
ErrorCode DEMO02_CATEGORY_NOT_EXISTS = new ErrorCode(1_001_201_001, "示例分类不存在");
ErrorCode DEMO02_CATEGORY_EXITS_CHILDREN = new ErrorCode(1_001_201_002, "存在存在子示例分类,无法删除");
ErrorCode DEMO02_CATEGORY_PARENT_NOT_EXITS = new ErrorCode(1_001_201_003,"父级示例分类不存在");
ErrorCode DEMO02_CATEGORY_PARENT_ERROR = new ErrorCode(1_001_201_004, "不能设置自己为父示例分类");
ErrorCode DEMO02_CATEGORY_NAME_DUPLICATE = new ErrorCode(1_001_201_005, "已经存在该名字的示例分类");
ErrorCode DEMO02_CATEGORY_PARENT_IS_CHILD = new ErrorCode(1_001_201_006, "不能设置自己的子示例分类为父示例分类");
ErrorCode DEMO03_STUDENT_NOT_EXISTS = new ErrorCode(1_001_201_007, "学生不存在");
ErrorCode DEMO03_GRADE_NOT_EXISTS = new ErrorCode(1_001_201_008, "学生班级不存在");
ErrorCode DEMO03_GRADE_EXISTS = new ErrorCode(1_001_201_009, "学生班级已存在");

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.service.codegen.CodegenService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
Expand Down Expand Up @@ -60,10 +60,19 @@ public CommonResult<List<DatabaseTableRespVO>> getDatabaseTableList(
return success(codegenService.getDatabaseTableList(dataSourceConfigId, name, comment));
}

@GetMapping("/table/list")
@Operation(summary = "获得表定义列表")
@Parameter(name = "dataSourceConfigId", description = "数据源配置的编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('infra:codegen:query')")
public CommonResult<List<CodegenTableRespVO>> getCodegenTableList(@RequestParam(value = "dataSourceConfigId") Long dataSourceConfigId) {
List<CodegenTableDO> list = codegenService.getCodegenTableList(dataSourceConfigId);
return success(CodegenConvert.INSTANCE.convertList05(list));
}

@GetMapping("/table/page")
@Operation(summary = "获得表定义分页")
@PreAuthorize("@ss.hasPermission('infra:codegen:query')")
public CommonResult<PageResult<CodegenTableRespVO>> getCodeGenTablePage(@Valid CodegenTablePageReqVO pageReqVO) {
public CommonResult<PageResult<CodegenTableRespVO>> getCodegenTablePage(@Valid CodegenTablePageReqVO pageReqVO) {
PageResult<CodegenTableDO> pageResult = codegenService.getCodegenTablePage(pageReqVO);
return success(CodegenConvert.INSTANCE.convertPage(pageResult));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ public class CodegenDetailRespVO {
@Schema(description = "字段定义")
private List<CodegenColumnRespVO> columns;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.column.CodegenColumnBaseVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTableBaseVO;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
Expand Down Expand Up @@ -37,12 +39,27 @@ public static class Table extends CodegenTableBaseVO {
private Long id;

@AssertTrue(message = "上级菜单不能为空,请前往 [修改生成配置 -> 生成信息] 界面,设置“上级菜单”字段")
@JsonIgnore
public boolean isParentMenuIdValid() {
// 生成场景为管理后台时,必须设置上级菜单,不然生成的菜单 SQL 是无父级菜单的
return ObjectUtil.notEqual(getScene(), CodegenSceneEnum.ADMIN.getScene())
|| getParentMenuId() != null;
}

@AssertTrue(message = "关联的父表信息不全")
@JsonIgnore
public boolean isSubValid() {
return ObjectUtil.notEqual(getTemplateType(), CodegenTemplateTypeEnum.SUB)
|| (ObjectUtil.isAllNotEmpty(getMasterTableId(), getSubJoinColumnId(), getSubJoinMany()));
}

@AssertTrue(message = "关联的树表信息不全")
@JsonIgnore
public boolean isTreeValid() {
return ObjectUtil.notEqual(getTemplateType(), CodegenTemplateTypeEnum.TREE)
|| (ObjectUtil.isAllNotEmpty(getTreeParentColumnId(), getTreeNameColumnId()));
}

}

@Schema(description = "更新表定义")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,16 @@ public class CodegenTableBaseVO {
@Schema(description = "父菜单编号", example = "1024")
private Long parentMenuId;

@Schema(description = "主表的编号", example = "2048")
private Long masterTableId;
@Schema(description = "子表关联主表的字段编号", example = "4096")
private Long subJoinColumnId;
@Schema(description = "主表与子表是否一对多", example = "4096")
private Boolean subJoinMany;

@Schema(description = "树表的父字段编号", example = "8192")
private Long treeParentColumnId;
@Schema(description = "树表的名字字段编号", example = "16384")
private Long treeNameColumnId;

}
Loading

0 comments on commit c8c0c84

Please sign in to comment.