代码生成:主子表、树形表的实现

pull/65/head
YunaiV 2023-11-17 20:46:02 +08:00
parent 95d5fc4a58
commit ae14ff2f95
237 changed files with 13452 additions and 1611 deletions

View File

@ -15,6 +15,13 @@ public class PageParam implements Serializable {
private static final Integer PAGE_NO = 1; private static final Integer PAGE_NO = 1;
private static final Integer PAGE_SIZE = 10; 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") @Schema(description = "页码,从 1 开始", requiredMode = Schema.RequiredMode.REQUIRED,example = "1")
@NotNull(message = "页码不能为空") @NotNull(message = "页码不能为空")
@Min(value = 1, message = "页码最小值为 1") @Min(value = 1, message = "页码最小值为 1")

View File

@ -238,7 +238,7 @@ public class CollectionUtils {
if (CollUtil.isEmpty(from)) { if (CollUtil.isEmpty(from)) {
return null; return null;
} }
assert from.size() > 0; // 断言,避免告警 assert !from.isEmpty(); // 断言,避免告警
T t = from.stream().max(Comparator.comparing(valueFunc)).get(); T t = from.stream().max(Comparator.comparing(valueFunc)).get();
return valueFunc.apply(t); return valueFunc.apply(t);
} }

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.json;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
@ -30,6 +31,7 @@ public class JsonUtils {
static { static {
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略 null 值
objectMapper.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化 objectMapper.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化
} }
@ -71,6 +73,20 @@ public class JsonUtils {
} }
} }
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) { public static <T> T parseObject(String text, Type type) {
if (StrUtil.isEmpty(text)) { if (StrUtil.isEmpty(text)) {
return null; return null;
@ -132,6 +148,20 @@ public class JsonUtils {
} }
} }
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) { public static JsonNode parseTree(String text) {
try { try {
return objectMapper.readTree(text); return objectMapper.readTree(text);

View File

@ -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());
}
}

View File

@ -50,4 +50,20 @@ public class StrUtils {
return Arrays.stream(integers).boxed().collect(Collectors.toList()); 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"));
}
} }

View File

@ -26,6 +26,12 @@ import java.util.List;
public interface BaseMapperX<T> extends MPJBaseMapper<T> { public interface BaseMapperX<T> extends MPJBaseMapper<T> {
default PageResult<T> selectPage(PageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) { 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 查询 // MyBatis Plus 查询
IPage<T> mpPage = MyBatisUtils.buildPage(pageParam); IPage<T> mpPage = MyBatisUtils.buildPage(pageParam);
selectPage(mpPage, queryWrapper); selectPage(mpPage, queryWrapper);
@ -93,10 +99,15 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
return selectList(new LambdaQueryWrapper<T>().in(field, values)); return selectList(new LambdaQueryWrapper<T>().in(field, values));
} }
@Deprecated
default List<T> selectList(SFunction<T, ?> leField, SFunction<T, ?> geField, Object value) { default List<T> selectList(SFunction<T, ?> leField, SFunction<T, ?> geField, Object value) {
return selectList(new LambdaQueryWrapper<T>().le(leField, value).ge(geField, 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));
}
/** /**
* *
* *
@ -128,8 +139,20 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
Db.updateBatchById(entities, 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); 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));
}
} }

View File

@ -42,9 +42,10 @@ public interface ErrorCodeConstants {
ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1_003_001_007, "同步失败,不存在改变"); 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_TABLE_COMMENT_IS_NULL = new ErrorCode(1_003_001_008, "数据库的表注释未填写");
ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1_003_001_009, "数据库的表字段({})注释未填写"); ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1_003_001_009, "数据库的表字段({})注释未填写");
ErrorCode CODEGEN_MASTER_TABLE_NOT_EXISTS = new ErrorCode(1_003_001_010, "主表(id={})定义不存在,请检查");
// ========== 字典类型测试1-001-005-000 ========== ErrorCode CODEGEN_SUB_COLUMN_NOT_EXISTS = new ErrorCode(1_003_001_011, "子表的字段(id={})不存在,请检查");
ErrorCode TEST_DEMO_NOT_EXISTS = new ErrorCode(1_001_005_000, "测试示例不存在"); 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 ========== // ========== 文件配置 1-001-006-000 ==========
ErrorCode FILE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_006_000, "文件配置不存在"); ErrorCode FILE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_006_000, "文件配置不存在");
@ -54,4 +55,19 @@ public interface ErrorCodeConstants {
ErrorCode DATA_SOURCE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_007_000, "数据源配置不存在"); ErrorCode DATA_SOURCE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_007_000, "数据源配置不存在");
ErrorCode DATA_SOURCE_CONFIG_NOT_OK = new ErrorCode(1_001_007_001, "数据源配置不正确,无法进行连接"); 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, "学生班级已存在");
} }

View File

@ -16,10 +16,10 @@ import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; 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.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.service.codegen.CodegenService; 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.Parameter;
import io.swagger.v3.oas.annotations.Parameters; 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.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -60,10 +60,19 @@ public class CodegenController {
return success(codegenService.getDatabaseTableList(dataSourceConfigId, name, comment)); 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") @GetMapping("/table/page")
@Operation(summary = "获得表定义分页") @Operation(summary = "获得表定义分页")
@PreAuthorize("@ss.hasPermission('infra:codegen:query')") @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); PageResult<CodegenTableDO> pageResult = codegenService.getCodegenTablePage(pageReqVO);
return success(CodegenConvert.INSTANCE.convertPage(pageResult)); return success(CodegenConvert.INSTANCE.convertPage(pageResult));
} }

View File

@ -4,6 +4,8 @@ import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.column.CodegenColumnBaseVO; 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.controller.admin.codegen.vo.table.CodegenTableBaseVO;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum; 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 io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -37,12 +39,27 @@ public class CodegenUpdateReqVO {
private Long id; private Long id;
@AssertTrue(message = "上级菜单不能为空,请前往 [修改生成配置 -> 生成信息] 界面,设置“上级菜单”字段") @AssertTrue(message = "上级菜单不能为空,请前往 [修改生成配置 -> 生成信息] 界面,设置“上级菜单”字段")
@JsonIgnore
public boolean isParentMenuIdValid() { public boolean isParentMenuIdValid() {
// 生成场景为管理后台时,必须设置上级菜单,不然生成的菜单 SQL 是无父级菜单的 // 生成场景为管理后台时,必须设置上级菜单,不然生成的菜单 SQL 是无父级菜单的
return ObjectUtil.notEqual(getScene(), CodegenSceneEnum.ADMIN.getScene()) return ObjectUtil.notEqual(getScene(), CodegenSceneEnum.ADMIN.getScene())
|| getParentMenuId() != null; || 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 = "更新表定义") @Schema(description = "更新表定义")

View File

@ -58,4 +58,16 @@ public class CodegenTableBaseVO {
@Schema(description = "父菜单编号", example = "1024") @Schema(description = "父菜单编号", example = "1024")
private Long parentMenuId; 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;
} }

View File

@ -0,0 +1,93 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactPageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactSaveReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo01.Demo01ContactDO;
import cn.iocoder.yudao.module.infra.service.demo.demo01.Demo01ContactService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
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.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 示例联系人")
@RestController
@RequestMapping("/infra/demo01-contact")
@Validated
public class Demo01ContactController {
@Resource
private Demo01ContactService demo01ContactService;
@PostMapping("/create")
@Operation(summary = "创建示例联系人")
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:create')")
public CommonResult<Long> createDemo01Contact(@Valid @RequestBody Demo01ContactSaveReqVO createReqVO) {
return success(demo01ContactService.createDemo01Contact(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新示例联系人")
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:update')")
public CommonResult<Boolean> updateDemo01Contact(@Valid @RequestBody Demo01ContactSaveReqVO updateReqVO) {
demo01ContactService.updateDemo01Contact(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除示例联系人")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:delete')")
public CommonResult<Boolean> deleteDemo01Contact(@RequestParam("id") Long id) {
demo01ContactService.deleteDemo01Contact(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得示例联系人")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:query')")
public CommonResult<Demo01ContactRespVO> getDemo01Contact(@RequestParam("id") Long id) {
Demo01ContactDO demo01Contact = demo01ContactService.getDemo01Contact(id);
return success(BeanUtils.toBean(demo01Contact, Demo01ContactRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得示例联系人分页")
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:query')")
public CommonResult<PageResult<Demo01ContactRespVO>> getDemo01ContactPage(@Valid Demo01ContactPageReqVO pageReqVO) {
PageResult<Demo01ContactDO> pageResult = demo01ContactService.getDemo01ContactPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, Demo01ContactRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出示例联系人 Excel")
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:export')")
@OperateLog(type = EXPORT)
public void exportDemo01ContactExcel(@Valid Demo01ContactPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<Demo01ContactDO> list = demo01ContactService.getDemo01ContactPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "示例联系人.xls", "数据", Demo01ContactRespVO.class,
BeanUtils.toBean(list, Demo01ContactRespVO.class));
}
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 示例联系人分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class Demo01ContactPageReqVO extends PageParam {
@Schema(description = "名字", example = "张三")
private String name;
@Schema(description = "性别", example = "1")
private Integer sex;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 示例联系人 Response VO")
@Data
@ExcelIgnoreUnannotated
public class Demo01ContactRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21555")
@ExcelProperty("编号")
private Long id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
@ExcelProperty("名字")
private String name;
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty(value = "性别", converter = DictConvert.class)
@DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
private Integer sex;
@Schema(description = "出生年", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("出生年")
private LocalDateTime birthday;
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对")
@ExcelProperty("简介")
private String description;
@Schema(description = "头像")
@ExcelProperty("头像")
private String avatar;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 示例联系人新增/修改 Request VO")
@Data
public class Demo01ContactSaveReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21555")
private Long id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
@NotEmpty(message = "名字不能为空")
private String name;
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "性别不能为空")
private Integer sex;
@Schema(description = "出生年", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "出生年不能为空")
private LocalDateTime birthday;
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对")
@NotEmpty(message = "简介不能为空")
private String description;
@Schema(description = "头像")
private String avatar;
}

View File

@ -0,0 +1,90 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryListReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategorySaveReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo02.Demo02CategoryDO;
import cn.iocoder.yudao.module.infra.service.demo.demo02.Demo02CategoryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
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.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 示例分类")
@RestController
@RequestMapping("/infra/demo02-category")
@Validated
public class Demo02CategoryController {
@Resource
private Demo02CategoryService demo02CategoryService;
@PostMapping("/create")
@Operation(summary = "创建示例分类")
@PreAuthorize("@ss.hasPermission('infra:demo02-category:create')")
public CommonResult<Long> createDemo02Category(@Valid @RequestBody Demo02CategorySaveReqVO createReqVO) {
return success(demo02CategoryService.createDemo02Category(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新示例分类")
@PreAuthorize("@ss.hasPermission('infra:demo02-category:update')")
public CommonResult<Boolean> updateDemo02Category(@Valid @RequestBody Demo02CategorySaveReqVO updateReqVO) {
demo02CategoryService.updateDemo02Category(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除示例分类")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:demo02-category:delete')")
public CommonResult<Boolean> deleteDemo02Category(@RequestParam("id") Long id) {
demo02CategoryService.deleteDemo02Category(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得示例分类")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('infra:demo02-category:query')")
public CommonResult<Demo02CategoryRespVO> getDemo02Category(@RequestParam("id") Long id) {
Demo02CategoryDO demo02Category = demo02CategoryService.getDemo02Category(id);
return success(BeanUtils.toBean(demo02Category, Demo02CategoryRespVO.class));
}
@GetMapping("/list")
@Operation(summary = "获得示例分类列表")
@PreAuthorize("@ss.hasPermission('infra:demo02-category:query')")
public CommonResult<List<Demo02CategoryRespVO>> getDemo02CategoryList(@Valid Demo02CategoryListReqVO listReqVO) {
List<Demo02CategoryDO> list = demo02CategoryService.getDemo02CategoryList(listReqVO);
return success(BeanUtils.toBean(list, Demo02CategoryRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出示例分类 Excel")
@PreAuthorize("@ss.hasPermission('infra:demo02-category:export')")
@OperateLog(type = EXPORT)
public void exportDemo02CategoryExcel(@Valid Demo02CategoryListReqVO listReqVO,
HttpServletResponse response) throws IOException {
List<Demo02CategoryDO> list = demo02CategoryService.getDemo02CategoryList(listReqVO);
// 导出 Excel
ExcelUtils.write(response, "示例分类.xls", "数据", Demo02CategoryRespVO.class,
BeanUtils.toBean(list, Demo02CategoryRespVO.class));
}
}

View File

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 示例分类列表 Request VO")
@Data
public class Demo02CategoryListReqVO {
@Schema(description = "名字", example = "芋艿")
private String name;
@Schema(description = "父级编号", example = "6080")
private Long parentId;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 示例分类 Response VO")
@Data
@ExcelIgnoreUnannotated
public class Demo02CategoryRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10304")
@ExcelProperty("编号")
private Long id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
@ExcelProperty("名字")
private String name;
@Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6080")
@ExcelProperty("父级编号")
private Long parentId;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,24 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 示例分类新增/修改 Request VO")
@Data
public class Demo02CategorySaveReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10304")
private Long id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
@NotEmpty(message = "名字不能为空")
private String name;
@Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6080")
@NotNull(message = "父级编号不能为空")
private Long parentId;
}

View File

@ -0,0 +1,197 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentSaveReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
import cn.iocoder.yudao.module.infra.service.demo.demo03.Demo03StudentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
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.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 学生")
@RestController
@RequestMapping("/infra/demo03-student")
@Validated
public class Demo03StudentController {
@Resource
private Demo03StudentService demo03StudentService;
@PostMapping("/create")
@Operation(summary = "创建学生")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:create')")
public CommonResult<Long> createDemo03Student(@Valid @RequestBody Demo03StudentSaveReqVO createReqVO) {
return success(demo03StudentService.createDemo03Student(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新学生")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:update')")
public CommonResult<Boolean> updateDemo03Student(@Valid @RequestBody Demo03StudentSaveReqVO updateReqVO) {
demo03StudentService.updateDemo03Student(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除学生")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
public CommonResult<Boolean> deleteDemo03Student(@RequestParam("id") Long id) {
demo03StudentService.deleteDemo03Student(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得学生")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
public CommonResult<Demo03StudentRespVO> getDemo03Student(@RequestParam("id") Long id) {
Demo03StudentDO demo03Student = demo03StudentService.getDemo03Student(id);
return success(BeanUtils.toBean(demo03Student, Demo03StudentRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得学生分页")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
public CommonResult<PageResult<Demo03StudentRespVO>> getDemo03StudentPage(@Valid Demo03StudentPageReqVO pageReqVO) {
PageResult<Demo03StudentDO> pageResult = demo03StudentService.getDemo03StudentPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, Demo03StudentRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出学生 Excel")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:export')")
@OperateLog(type = EXPORT)
public void exportDemo03StudentExcel(@Valid Demo03StudentPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<Demo03StudentDO> list = demo03StudentService.getDemo03StudentPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "学生.xls", "数据", Demo03StudentRespVO.class,
BeanUtils.toBean(list, Demo03StudentRespVO.class));
}
// ==================== 子表(学生课程) ====================
@GetMapping("/demo03-course/page")
@Operation(summary = "获得学生课程分页")
@Parameter(name = "studentId", description = "学生编号")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
public CommonResult<PageResult<Demo03CourseDO>> getDemo03CoursePage(PageParam pageReqVO,
@RequestParam("studentId") Long studentId) {
return success(demo03StudentService.getDemo03CoursePage(pageReqVO, studentId));
}
@PostMapping("/demo03-course/create")
@Operation(summary = "创建学生课程")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:create')")
public CommonResult<Long> createDemo03Course(@Valid @RequestBody Demo03CourseDO demo03Course) {
return success(demo03StudentService.createDemo03Course(demo03Course));
}
@PutMapping("/demo03-course/update")
@Operation(summary = "更新学生课程")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:update')")
public CommonResult<Boolean> updateDemo03Course(@Valid @RequestBody Demo03CourseDO demo03Course) {
demo03StudentService.updateDemo03Course(demo03Course);
return success(true);
}
@DeleteMapping("/demo03-course/delete")
@Parameter(name = "id", description = "编号", required = true)
@Operation(summary = "删除学生课程")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
public CommonResult<Boolean> deleteDemo03Course(@RequestParam("id") Long id) {
demo03StudentService.deleteDemo03Course(id);
return success(true);
}
@GetMapping("/demo03-course/get")
@Operation(summary = "获得学生课程")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
public CommonResult<Demo03CourseDO> getDemo03Course(@RequestParam("id") Long id) {
return success(demo03StudentService.getDemo03Course(id));
}
@GetMapping("/demo03-course/list-by-student-id")
@Operation(summary = "获得学生课程列表")
@Parameter(name = "studentId", description = "学生编号")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
public CommonResult<List<Demo03CourseDO>> getDemo03CourseListByStudentId(@RequestParam("studentId") Long studentId) {
return success(demo03StudentService.getDemo03CourseListByStudentId(studentId));
}
// ==================== 子表(学生班级) ====================
@GetMapping("/demo03-grade/page")
@Operation(summary = "获得学生班级分页")
@Parameter(name = "studentId", description = "学生编号")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
public CommonResult<PageResult<Demo03GradeDO>> getDemo03GradePage(PageParam pageReqVO,
@RequestParam("studentId") Long studentId) {
return success(demo03StudentService.getDemo03GradePage(pageReqVO, studentId));
}
@PostMapping("/demo03-grade/create")
@Operation(summary = "创建学生班级")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:create')")
public CommonResult<Long> createDemo03Grade(@Valid @RequestBody Demo03GradeDO demo03Grade) {
return success(demo03StudentService.createDemo03Grade(demo03Grade));
}
@PutMapping("/demo03-grade/update")
@Operation(summary = "更新学生班级")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:update')")
public CommonResult<Boolean> updateDemo03Grade(@Valid @RequestBody Demo03GradeDO demo03Grade) {
demo03StudentService.updateDemo03Grade(demo03Grade);
return success(true);
}
@DeleteMapping("/demo03-grade/delete")
@Parameter(name = "id", description = "编号", required = true)
@Operation(summary = "删除学生班级")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
public CommonResult<Boolean> deleteDemo03Grade(@RequestParam("id") Long id) {
demo03StudentService.deleteDemo03Grade(id);
return success(true);
}
@GetMapping("/demo03-grade/get")
@Operation(summary = "获得学生班级")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
public CommonResult<Demo03GradeDO> getDemo03Grade(@RequestParam("id") Long id) {
return success(demo03StudentService.getDemo03Grade(id));
}
@GetMapping("/demo03-grade/get-by-student-id")
@Operation(summary = "获得学生班级")
@Parameter(name = "studentId", description = "学生编号")
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
public CommonResult<Demo03GradeDO> getDemo03GradeByStudentId(@RequestParam("studentId") Long studentId) {
return success(demo03StudentService.getDemo03GradeByStudentId(studentId));
}
}

View File

@ -0,0 +1 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03;

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.infra.controller.admin.test.vo; package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
@ -11,29 +11,23 @@ import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 字典类型分页 Request VO") @Schema(description = "管理后台 - 学生分页 Request VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class TestDemoPageReqVO extends PageParam { public class Demo03StudentPageReqVO extends PageParam {
@Schema(description = "名字") @Schema(description = "名字", example = "芋艿")
private String name; private String name;
@Schema(description = "状态") @Schema(description = "性别")
private Integer status; private Integer sex;
@Schema(description = "类型") @Schema(description = "简介", example = "随便")
private Integer type; private String description;
@Schema(description = "分类")
private Integer category;
@Schema(description = "备注")
private String remark;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@Schema(description = "创建时间") @Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime; private LocalDateTime[] createTime;
} }

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 学生 Response VO")
@Data
@ExcelIgnoreUnannotated
public class Demo03StudentRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8525")
@ExcelProperty("编号")
private Long id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
@ExcelProperty("名字")
private String name;
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty(value = "性别", converter = DictConvert.class)
@DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
private Integer sex;
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("出生日期")
private LocalDateTime birthday;
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "随便")
@ExcelProperty("简介")
private String description;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 学生新增/修改 Request VO")
@Data
public class Demo03StudentSaveReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8525")
private Long id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
@NotEmpty(message = "名字不能为空")
private String name;
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "性别不能为空")
private Integer sex;
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "出生日期不能为空")
private LocalDateTime birthday;
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "随便")
@NotEmpty(message = "简介不能为空")
private String description;
private List<Demo03CourseDO> demo03Courses;
private Demo03GradeDO demo03Grade;
}

View File

@ -0,0 +1,8 @@
/**
*
*
* 1. demo01
* 2. demo02
* 3. demo03+ ERP +
*/
package cn.iocoder.yudao.module.infra.controller.admin.demo;

View File

@ -1,19 +0,0 @@
### 请求 /infra/test-demo/get 接口 => 成功
GET {{baseUrl}}/infra/test-demo/get?id=106
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
### 请求 /infra/test-demo/update 接口 => 成功
PUT {{baseUrl}}/infra/test-demo/update
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
Content-Type: application/json
{
"id": 106,
"name": "测试",
"status": "0",
"type": 1,
"category": 1
}

View File

@ -1,97 +0,0 @@
package cn.iocoder.yudao.module.infra.controller.admin.test;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.*;
import cn.iocoder.yudao.module.infra.convert.test.TestDemoConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO;
import cn.iocoder.yudao.module.infra.service.test.TestDemoService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 字典类型")
@RestController
@RequestMapping("/infra/test-demo")
@Validated
public class TestDemoController {
@Resource
private TestDemoService testDemoService;
@PostMapping("/create")
@Operation(summary = "创建字典类型")
@PreAuthorize("@ss.hasPermission('infra:test-demo:create')")
public CommonResult<Long> createTestDemo(@Valid @RequestBody TestDemoCreateReqVO createReqVO) {
return success(testDemoService.createTestDemo(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新字典类型")
@PreAuthorize("@ss.hasPermission('infra:test-demo:update')")
public CommonResult<Boolean> updateTestDemo(@Valid @RequestBody TestDemoUpdateReqVO updateReqVO) {
testDemoService.updateTestDemo(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除字典类型")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:test-demo:delete')")
public CommonResult<Boolean> deleteTestDemo(@RequestParam("id") Long id) {
testDemoService.deleteTestDemo(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得字典类型")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('infra:test-demo:query')")
public CommonResult<TestDemoRespVO> getTestDemo(@RequestParam("id") Long id) {
TestDemoDO testDemo = testDemoService.getTestDemo(id);
return success(TestDemoConvert.INSTANCE.convert(testDemo));
}
@GetMapping("/list")
@Operation(summary = "获得字典类型列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
@PreAuthorize("@ss.hasPermission('infra:test-demo:query')")
public CommonResult<List<TestDemoRespVO>> getTestDemoList(@RequestParam("ids") Collection<Long> ids) {
List<TestDemoDO> list = testDemoService.getTestDemoList(ids);
return success(TestDemoConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@Operation(summary = "获得字典类型分页")
@PreAuthorize("@ss.hasPermission('infra:test-demo:query')") public CommonResult<PageResult<TestDemoRespVO>> getTestDemoPage(@Valid TestDemoPageReqVO pageVO) {
PageResult<TestDemoDO> pageResult = testDemoService.getTestDemoPage(pageVO);
return success(TestDemoConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@Operation(summary = "导出字典类型 Excel")
@PreAuthorize("@ss.hasPermission('infra:test-demo:export')") @OperateLog(type = EXPORT)
public void exportTestDemoExcel(@Valid TestDemoExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<TestDemoDO> list = testDemoService.getTestDemoList(exportReqVO);
// 导出 Excel
List<TestDemoExcelVO> datas = TestDemoConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "字典类型.xls", "数据", TestDemoExcelVO.class, datas);
}
}

View File

@ -1,34 +0,0 @@
package cn.iocoder.yudao.module.infra.controller.admin.test.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* Base VO VO 使
* VO Swagger
*/
@Data
public class TestDemoBaseVO {
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "名字不能为空")
private String name;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "状态不能为空")
private Integer status;
@Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "类型不能为空")
private Integer type;
@Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "分类不能为空")
private Integer category;
@Schema(description = "备注")
private String remark;
}

View File

@ -1,14 +0,0 @@
package cn.iocoder.yudao.module.infra.controller.admin.test.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 字典类型创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TestDemoCreateReqVO extends TestDemoBaseVO {
}

View File

@ -1,37 +0,0 @@
package cn.iocoder.yudao.module.infra.controller.admin.test.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* Excel VO
*
* @author
*/
@Data
public class TestDemoExcelVO {
@ExcelProperty("编号")
private Long id;
@ExcelProperty("名字")
private String name;
@ExcelProperty("状态")
private Integer status;
@ExcelProperty("类型")
private Integer type;
@ExcelProperty("分类")
private Integer category;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -1,34 +0,0 @@
package cn.iocoder.yudao.module.infra.controller.admin.test.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 字典类型 Excel 导出 Request VO参数和 TestDemoPageReqVO 是一致的")
@Data
public class TestDemoExportReqVO {
@Schema(description = "名字")
private String name;
@Schema(description = "状态")
private Integer status;
@Schema(description = "类型")
private Integer type;
@Schema(description = "分类")
private Integer category;
@Schema(description = "备注")
private String remark;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@Schema(description = "创建时间")
private LocalDateTime[] createTime;
}

View File

@ -1,22 +0,0 @@
package cn.iocoder.yudao.module.infra.controller.admin.test.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 字典类型 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TestDemoRespVO extends TestDemoBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED)
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -1,20 +0,0 @@
package cn.iocoder.yudao.module.infra.controller.admin.test.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 字典类型更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TestDemoUpdateReqVO extends TestDemoBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "编号不能为空")
private Long id;
}

View File

@ -56,7 +56,7 @@ public interface CodegenConvert {
// ========== CodegenTableDO 相关 ========== // ========== CodegenTableDO 相关 ==========
// List<CodegenTableRespVO> convertList02(List<CodegenTableDO> list); List<CodegenTableRespVO> convertList05(List<CodegenTableDO> list);
CodegenTableRespVO convert(CodegenTableDO bean); CodegenTableRespVO convert(CodegenTableDO bean);

View File

@ -1,36 +0,0 @@
package cn.iocoder.yudao.module.infra.convert.test;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoCreateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoExcelVO;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoUpdateReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* Convert
*
* @author
*/
@Mapper
public interface TestDemoConvert {
TestDemoConvert INSTANCE = Mappers.getMapper(TestDemoConvert.class);
TestDemoDO convert(TestDemoCreateReqVO bean);
TestDemoDO convert(TestDemoUpdateReqVO bean);
TestDemoRespVO convert(TestDemoDO bean);
List<TestDemoRespVO> convertList(List<TestDemoDO> list);
PageResult<TestDemoRespVO> convertPage(PageResult<TestDemoDO> page);
List<TestDemoExcelVO> convertList02(List<TestDemoDO> list);
}

View File

@ -5,7 +5,6 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
@ -117,4 +116,43 @@ public class CodegenTableDO extends BaseDO {
*/ */
private Long parentMenuId; private Long parentMenuId;
// ========== 主子表相关字段 ==========
/**
*
*
* {@link CodegenTableDO#getId()}
*/
private Long masterTableId;
/**
*
*
* {@link CodegenColumnDO#getId()}
*/
private Long subJoinColumnId;
/**
*
*
* true
* false
*/
private Boolean subJoinMany;
// ========== 树表相关字段 ==========
/**
*
*
* {@link CodegenColumnDO#getId()}
*/
private Long treeParentColumnId;
/**
*
*
* select
*
* {@link CodegenColumnDO#getId()}
*/
private Long treeNameColumnId;
} }

View File

@ -0,0 +1,54 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo01;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.time.LocalDateTime;
/**
* DO
*
* @author
*/
@TableName("infra_demo01_contact")
@KeySequence("infra_demo01_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Demo01ContactDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
*
*/
private String name;
/**
*
*
* {@link TODO system_user_sex }
*/
private Integer sex;
/**
*
*/
private LocalDateTime birthday;
/**
*
*/
private String description;
/**
*
*/
private String avatar;
}

View File

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo02;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* DO
*
* @author
*/
@TableName("infra_demo02_category")
@KeySequence("infra_demo02_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Demo02CategoryDO extends BaseDO {
public static final Long PARENT_ID_ROOT = 0L;
/**
*
*/
@TableId
private Long id;
/**
*
*/
private String name;
/**
*
*/
private Long parentId;
}

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.test; package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.KeySequence;
@ -7,44 +7,36 @@ import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*; import lombok.*;
/** /**
* DO * DO
* *
* @author * @author
*/ */
@TableName("infra_test_demo") @TableName("infra_demo03_course")
@KeySequence("infra_test_demo_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @KeySequence("infra_demo03_course_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
@Builder @Builder
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class TestDemoDO extends BaseDO { public class Demo03CourseDO extends BaseDO {
/** /**
* *
*/ */
@TableId @TableId
private Long id; private Long id;
/**
*
*/
private Long studentId;
/** /**
* *
*/ */
private String name; private String name;
/** /**
* *
*/ */
private Integer status; private Integer score;
/**
*
*/
private Integer type;
/**
*
*/
private Integer category;
/**
*
*/
private String remark;
} }

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* DO
*
* @author
*/
@TableName("infra_demo03_grade")
@KeySequence("infra_demo03_grade_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Demo03GradeDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
*
*/
private Long studentId;
/**
*
*/
private String name;
/**
*
*/
private String teacher;
}

View File

@ -0,0 +1,50 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.time.LocalDateTime;
/**
* DO
*
* @author
*/
@TableName("infra_demo03_student")
@KeySequence("infra_demo03_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Demo03StudentDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
*
*/
private String name;
/**
*
*
* {@link TODO system_user_sex }
*/
private Integer sex;
/**
*
*/
private LocalDateTime birthday;
/**
*
*/
private String description;
}

View File

@ -29,4 +29,9 @@ public interface CodegenTableMapper extends BaseMapperX<CodegenTableDO> {
return selectList(CodegenTableDO::getDataSourceConfigId, dataSourceConfigId); return selectList(CodegenTableDO::getDataSourceConfigId, dataSourceConfigId);
} }
default List<CodegenTableDO> selectListByTemplateTypeAndMasterTableId(Integer templateType, Long masterTableId) {
return selectList(CodegenTableDO::getTemplateType, templateType,
CodegenTableDO::getMasterTableId, masterTableId);
}
} }

View File

@ -0,0 +1,26 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo01;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactPageReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo01.Demo01ContactDO;
import org.apache.ibatis.annotations.Mapper;
/**
* Mapper
*
* @author
*/
@Mapper
public interface Demo01ContactMapper extends BaseMapperX<Demo01ContactDO> {
default PageResult<Demo01ContactDO> selectPage(Demo01ContactPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<Demo01ContactDO>()
.likeIfPresent(Demo01ContactDO::getName, reqVO.getName())
.eqIfPresent(Demo01ContactDO::getSex, reqVO.getSex())
.betweenIfPresent(Demo01ContactDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(Demo01ContactDO::getId));
}
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo02;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryListReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo02.Demo02CategoryDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* Mapper
*
* @author
*/
@Mapper
public interface Demo02CategoryMapper extends BaseMapperX<Demo02CategoryDO> {
default List<Demo02CategoryDO> selectList(Demo02CategoryListReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<Demo02CategoryDO>()
.likeIfPresent(Demo02CategoryDO::getName, reqVO.getName())
.eqIfPresent(Demo02CategoryDO::getParentId, reqVO.getParentId())
.betweenIfPresent(Demo02CategoryDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(Demo02CategoryDO::getId));
}
default Demo02CategoryDO selectByParentIdAndName(Long parentId, String name) {
return selectOne(Demo02CategoryDO::getParentId, parentId, Demo02CategoryDO::getName, name);
}
default Long selectCountByParentId(Long parentId) {
return selectCount(Demo02CategoryDO::getParentId, parentId);
}
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* Mapper
*
* @author
*/
@Mapper
public interface Demo03CourseMapper extends BaseMapperX<Demo03CourseDO> {
default PageResult<Demo03CourseDO> selectPage(PageParam reqVO, Long studentId) {
return selectPage(reqVO, new LambdaQueryWrapperX<Demo03CourseDO>()
.eq(Demo03CourseDO::getStudentId, studentId)
.orderByDesc(Demo03CourseDO::getId));
}
default List<Demo03CourseDO> selectListByStudentId(Long studentId) {
return selectList(Demo03CourseDO::getStudentId, studentId);
}
default int deleteByStudentId(Long studentId) {
return delete(Demo03CourseDO::getStudentId, studentId);
}
}

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
import org.apache.ibatis.annotations.Mapper;
/**
* Mapper
*
* @author
*/
@Mapper
public interface Demo03GradeMapper extends BaseMapperX<Demo03GradeDO> {
default PageResult<Demo03GradeDO> selectPage(PageParam reqVO, Long studentId) {
return selectPage(reqVO, new LambdaQueryWrapperX<Demo03GradeDO>()
.eq(Demo03GradeDO::getStudentId, studentId)
.orderByDesc(Demo03GradeDO::getId));
}
default Demo03GradeDO selectByStudentId(Long studentId) {
return selectOne(Demo03GradeDO::getStudentId, studentId);
}
default int deleteByStudentId(Long studentId) {
return delete(Demo03GradeDO::getStudentId, studentId);
}
}

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
import org.apache.ibatis.annotations.Mapper;
/**
* Mapper
*
* @author
*/
@Mapper
public interface Demo03StudentMapper extends BaseMapperX<Demo03StudentDO> {
default PageResult<Demo03StudentDO> selectPage(Demo03StudentPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<Demo03StudentDO>()
.likeIfPresent(Demo03StudentDO::getName, reqVO.getName())
.eqIfPresent(Demo03StudentDO::getSex, reqVO.getSex())
.eqIfPresent(Demo03StudentDO::getDescription, reqVO.getDescription())
.betweenIfPresent(Demo03StudentDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(Demo03StudentDO::getId));
}
}

View File

@ -1,45 +0,0 @@
package cn.iocoder.yudao.module.infra.dal.mysql.test;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoExportReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoPageReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* Mapper
*
* @author
*/
@Mapper
public interface TestDemoMapper extends BaseMapperX<TestDemoDO> {
default PageResult<TestDemoDO> selectPage(TestDemoPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<TestDemoDO>()
.likeIfPresent(TestDemoDO::getName, reqVO.getName())
.eqIfPresent(TestDemoDO::getStatus, reqVO.getStatus())
.eqIfPresent(TestDemoDO::getType, reqVO.getType())
.eqIfPresent(TestDemoDO::getCategory, reqVO.getCategory())
.eqIfPresent(TestDemoDO::getRemark, reqVO.getRemark())
.betweenIfPresent(TestDemoDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(TestDemoDO::getId));
}
default List<TestDemoDO> selectList(TestDemoExportReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<TestDemoDO>()
.likeIfPresent(TestDemoDO::getName, reqVO.getName())
.eqIfPresent(TestDemoDO::getStatus, reqVO.getStatus())
.eqIfPresent(TestDemoDO::getType, reqVO.getType())
.eqIfPresent(TestDemoDO::getCategory, reqVO.getCategory())
.eqIfPresent(TestDemoDO::getRemark, reqVO.getRemark())
.betweenIfPresent(TestDemoDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(TestDemoDO::getId));
}
List<TestDemoDO> selectList2();
}

View File

@ -16,8 +16,8 @@ public enum CodegenColumnHtmlTypeEnum {
RADIO("radio"), // 单选框 RADIO("radio"), // 单选框
CHECKBOX("checkbox"), // 复选框 CHECKBOX("checkbox"), // 复选框
DATETIME("datetime"), // 日期控件 DATETIME("datetime"), // 日期控件
UPLOAD_IMAGE("upload_image"), // 上传图片 IMAGE_UPLOAD("imageUpload"), // 上传图片
UPLOAD_FILE("upload_file"), // 上传文件 FILE_UPLOAD("fileUpload"), // 上传文件
EDITOR("editor"), // 富文本控件 EDITOR("editor"), // 富文本控件
; ;

View File

@ -1,8 +1,11 @@
package cn.iocoder.yudao.module.infra.enums.codegen; package cn.iocoder.yudao.module.infra.enums.codegen;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import java.util.Objects;
/** /**
* *
* *
@ -12,8 +15,13 @@ import lombok.Getter;
@Getter @Getter
public enum CodegenTemplateTypeEnum { public enum CodegenTemplateTypeEnum {
CRUD(1), // 单表(增删改查) ONE(1), // 单表(增删改查)
TREE(2), // 树表(增删改查) TREE(2), // 树表(增删改查)
MASTER_NORMAL(10), // 主子表 - 主表 - 普通模式
MASTER_ERP(11), // 主子表 - 主表 - ERP 模式
MASTER_INNER(12), // 主子表 - 主表 - 内嵌模式
SUB(15), // 主子表 - 子表
; ;
/** /**
@ -21,4 +29,25 @@ public enum CodegenTemplateTypeEnum {
*/ */
private final Integer type; private final Integer type;
/**
*
*
* @param type
* @return
*/
public static boolean isMaster(Integer type) {
return ObjectUtils.equalsAny(type,
MASTER_NORMAL.type, MASTER_ERP.type, MASTER_INNER.type);
}
/**
*
*
* @param type
* @return
*/
public static boolean isTree(Integer type) {
return Objects.equals(type, TREE.type);
}
} }

View File

@ -48,6 +48,14 @@ public interface CodegenService {
*/ */
void deleteCodegen(Long tableId); void deleteCodegen(Long tableId);
/**
*
*
* @param dataSourceConfigId
* @return
*/
List<CodegenTableDO> getCodegenTableList(Long dataSourceConfigId);
/** /**
* *
* *

View File

@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper; import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper; import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties; import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties;
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder; import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder;
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine; import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine;
@ -25,10 +26,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -129,6 +127,16 @@ public class CodegenServiceImpl implements CodegenService {
if (codegenTableMapper.selectById(updateReqVO.getTable().getId()) == null) { if (codegenTableMapper.selectById(updateReqVO.getTable().getId()) == null) {
throw exception(CODEGEN_TABLE_NOT_EXISTS); throw exception(CODEGEN_TABLE_NOT_EXISTS);
} }
// 校验主表字段存在
if (Objects.equals(updateReqVO.getTable().getTemplateType(), CodegenTemplateTypeEnum.SUB.getType())) {
if (codegenTableMapper.selectById(updateReqVO.getTable().getMasterTableId()) == null) {
throw exception(CODEGEN_MASTER_TABLE_NOT_EXISTS, updateReqVO.getTable().getMasterTableId());
}
if (CollUtil.findOne(updateReqVO.getColumns(), // 关联主表的字段不存在
column -> column.getId().equals(updateReqVO.getTable().getSubJoinColumnId())) == null) {
throw exception(CODEGEN_SUB_COLUMN_NOT_EXISTS, updateReqVO.getTable().getSubJoinColumnId());
}
}
// 更新 table 表定义 // 更新 table 表定义
CodegenTableDO updateTableObj = CodegenConvert.INSTANCE.convert(updateReqVO.getTable()); CodegenTableDO updateTableObj = CodegenConvert.INSTANCE.convert(updateReqVO.getTable());
@ -208,6 +216,11 @@ public class CodegenServiceImpl implements CodegenService {
codegenColumnMapper.deleteListByTableId(tableId); codegenColumnMapper.deleteListByTableId(tableId);
} }
@Override
public List<CodegenTableDO> getCodegenTableList(Long dataSourceConfigId) {
return codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId);
}
@Override @Override
public PageResult<CodegenTableDO> getCodegenTablePage(CodegenTablePageReqVO pageReqVO) { public PageResult<CodegenTableDO> getCodegenTablePage(CodegenTablePageReqVO pageReqVO) {
return codegenTableMapper.selectPage(pageReqVO); return codegenTableMapper.selectPage(pageReqVO);
@ -235,14 +248,34 @@ public class CodegenServiceImpl implements CodegenService {
throw exception(CODEGEN_COLUMN_NOT_EXISTS); throw exception(CODEGEN_COLUMN_NOT_EXISTS);
} }
// 如果是主子表,则加载对应的子表信息
List<CodegenTableDO> subTables = null;
List<List<CodegenColumnDO>> subColumnsList = null;
if (CodegenTemplateTypeEnum.isMaster(table.getTemplateType())) {
// 校验子表存在
subTables = codegenTableMapper.selectListByTemplateTypeAndMasterTableId(
CodegenTemplateTypeEnum.SUB.getType(), tableId);
if (CollUtil.isEmpty(subTables)) {
throw exception(CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_TABLE);
}
// 校验子表的关联字段存在
subColumnsList = new ArrayList<>();
for (CodegenTableDO subTable : subTables) {
List<CodegenColumnDO> subColumns = codegenColumnMapper.selectListByTableId(subTable.getId());
if (CollUtil.findOne(subColumns, column -> column.getId().equals(subTable.getSubJoinColumnId())) == null) {
throw exception(CODEGEN_SUB_COLUMN_NOT_EXISTS, subTable.getId());
}
subColumnsList.add(subColumns);
}
}
// 执行生成 // 执行生成
return codegenEngine.execute(table, columns); return codegenEngine.execute(table, columns, subTables, subColumnsList);
} }
@Override @Override
public List<DatabaseTableRespVO> getDatabaseTableList(Long dataSourceConfigId, String name, String comment) { public List<DatabaseTableRespVO> getDatabaseTableList(Long dataSourceConfigId, String name, String comment) {
List<TableInfo> tables = databaseTableService.getTableList(dataSourceConfigId, name, comment); List<TableInfo> tables = databaseTableService.getTableList(dataSourceConfigId, name, comment);
// 移除已经生成的表
// 移除在 Codegen 中,已经存在的 // 移除在 Codegen 中,已经存在的
Set<String> existsTables = CollectionUtils.convertSet( Set<String> existsTables = CollectionUtils.convertSet(
codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId), CodegenTableDO::getTableName); codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId), CodegenTableDO::getTableName);

View File

@ -49,8 +49,8 @@ public class CodegenBuilder {
.put("status", CodegenColumnHtmlTypeEnum.RADIO) .put("status", CodegenColumnHtmlTypeEnum.RADIO)
.put("sex", CodegenColumnHtmlTypeEnum.RADIO) .put("sex", CodegenColumnHtmlTypeEnum.RADIO)
.put("type", CodegenColumnHtmlTypeEnum.SELECT) .put("type", CodegenColumnHtmlTypeEnum.SELECT)
.put("image", CodegenColumnHtmlTypeEnum.UPLOAD_IMAGE) .put("image", CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD)
.put("file", CodegenColumnHtmlTypeEnum.UPLOAD_FILE) .put("file", CodegenColumnHtmlTypeEnum.FILE_UPLOAD)
.put("content", CodegenColumnHtmlTypeEnum.EDITOR) .put("content", CodegenColumnHtmlTypeEnum.EDITOR)
.put("description", CodegenColumnHtmlTypeEnum.EDITOR) .put("description", CodegenColumnHtmlTypeEnum.EDITOR)
.put("demo", CodegenColumnHtmlTypeEnum.EDITOR) .put("demo", CodegenColumnHtmlTypeEnum.EDITOR)
@ -63,7 +63,7 @@ public class CodegenBuilder {
*/ */
public static final String TENANT_ID_FIELD = "tenantId"; public static final String TENANT_ID_FIELD = "tenantId";
/** /**
* {@link cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO} * {@link BaseDO}
*/ */
public static final Set<String> BASE_DO_FIELDS = new HashSet<>(); public static final Set<String> BASE_DO_FIELDS = new HashSet<>();
/** /**
@ -118,7 +118,7 @@ public class CodegenBuilder {
table.setClassName(upperFirst(toCamelCase(subAfter(tableName, '_', false)))); table.setClassName(upperFirst(toCamelCase(subAfter(tableName, '_', false))));
// 去除结尾的表,作为类描述 // 去除结尾的表,作为类描述
table.setClassComment(StrUtil.removeSuffixIgnoreCase(table.getTableComment(), "表")); table.setClassComment(StrUtil.removeSuffixIgnoreCase(table.getTableComment(), "表"));
table.setTemplateType(CodegenTemplateTypeEnum.CRUD.getType()); table.setTemplateType(CodegenTemplateTypeEnum.ONE.getType());
} }
public List<CodegenColumnDO> buildColumns(Long tableId, List<TableField> tableFields) { public List<CodegenColumnDO> buildColumns(Long tableId, List<TableField> tableFields) {

View File

@ -1,6 +1,8 @@
package cn.iocoder.yudao.module.infra.service.codegen.inner; package cn.iocoder.yudao.module.infra.service.codegen.inner;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.template.TemplateConfig; import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine; import cn.hutool.extra.template.TemplateEngine;
@ -12,7 +14,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
@ -25,7 +29,9 @@ 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.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties; import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableTable; import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Table; import com.google.common.collect.Table;
@ -33,10 +39,7 @@ import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.HashMap; import java.util.*;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static cn.hutool.core.map.MapUtil.getStr; import static cn.hutool.core.map.MapUtil.getStr;
import static cn.hutool.core.text.CharSequenceUtil.*; import static cn.hutool.core.text.CharSequenceUtil.*;
@ -60,20 +63,19 @@ public class CodegenEngine {
*/ */
private static final Map<String, String> SERVER_TEMPLATES = MapUtil.<String, String>builder(new LinkedHashMap<>()) // 有序 private static final Map<String, String> SERVER_TEMPLATES = MapUtil.<String, String>builder(new LinkedHashMap<>()) // 有序
// Java module-biz Main // Java module-biz Main
.put(javaTemplatePath("controller/vo/baseVO"), javaModuleImplVOFilePath("BaseVO"))
.put(javaTemplatePath("controller/vo/createReqVO"), javaModuleImplVOFilePath("CreateReqVO"))
.put(javaTemplatePath("controller/vo/pageReqVO"), javaModuleImplVOFilePath("PageReqVO")) .put(javaTemplatePath("controller/vo/pageReqVO"), javaModuleImplVOFilePath("PageReqVO"))
.put(javaTemplatePath("controller/vo/listReqVO"), javaModuleImplVOFilePath("ListReqVO"))
.put(javaTemplatePath("controller/vo/respVO"), javaModuleImplVOFilePath("RespVO")) .put(javaTemplatePath("controller/vo/respVO"), javaModuleImplVOFilePath("RespVO"))
.put(javaTemplatePath("controller/vo/updateReqVO"), javaModuleImplVOFilePath("UpdateReqVO")) .put(javaTemplatePath("controller/vo/saveReqVO"), javaModuleImplVOFilePath("SaveReqVO"))
.put(javaTemplatePath("controller/vo/exportReqVO"), javaModuleImplVOFilePath("ExportReqVO"))
.put(javaTemplatePath("controller/vo/excelVO"), javaModuleImplVOFilePath("ExcelVO"))
.put(javaTemplatePath("controller/controller"), javaModuleImplControllerFilePath()) .put(javaTemplatePath("controller/controller"), javaModuleImplControllerFilePath())
.put(javaTemplatePath("convert/convert"),
javaModuleImplMainFilePath("convert/${table.businessName}/${table.className}Convert"))
.put(javaTemplatePath("dal/do"), .put(javaTemplatePath("dal/do"),
javaModuleImplMainFilePath("dal/dataobject/${table.businessName}/${table.className}DO")) javaModuleImplMainFilePath("dal/dataobject/${table.businessName}/${table.className}DO"))
.put(javaTemplatePath("dal/do_sub"), // 特殊:主子表专属逻辑
javaModuleImplMainFilePath("dal/dataobject/${table.businessName}/${subTable.className}DO"))
.put(javaTemplatePath("dal/mapper"), .put(javaTemplatePath("dal/mapper"),
javaModuleImplMainFilePath("dal/mysql/${table.businessName}/${table.className}Mapper")) javaModuleImplMainFilePath("dal/mysql/${table.businessName}/${table.className}Mapper"))
.put(javaTemplatePath("dal/mapper_sub"), // 特殊:主子表专属逻辑
javaModuleImplMainFilePath("dal/mysql/${table.businessName}/${subTable.className}Mapper"))
.put(javaTemplatePath("dal/mapper.xml"), mapperXmlFilePath()) .put(javaTemplatePath("dal/mapper.xml"), mapperXmlFilePath())
.put(javaTemplatePath("service/serviceImpl"), .put(javaTemplatePath("service/serviceImpl"),
javaModuleImplMainFilePath("service/${table.businessName}/${table.className}ServiceImpl")) javaModuleImplMainFilePath("service/${table.businessName}/${table.className}ServiceImpl"))
@ -104,11 +106,21 @@ public class CodegenEngine {
vueFilePath("api/${table.moduleName}/${classNameVar}.js")) vueFilePath("api/${table.moduleName}/${classNameVar}.js"))
// Vue3 标准模版 // Vue3 标准模版
.put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/index.vue"), .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/index.vue"),
vue3FilePath("views/${table.moduleName}/${classNameVar}/index.vue")) vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue"))
.put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/form.vue"), .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/form.vue"),
vue3FilePath("views/${table.moduleName}/${classNameVar}/${simpleClassName}Form.vue")) vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Form.vue"))
.put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/form_sub_normal.vue"), // 特殊:主子表专属逻辑
vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue"))
.put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/form_sub_inner.vue"), // 特殊:主子表专属逻辑
vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue"))
.put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/form_sub_erp.vue"), // 特殊:主子表专属逻辑
vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue"))
.put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/list_sub_inner.vue"), // 特殊:主子表专属逻辑
vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue"))
.put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/list_sub_erp.vue"), // 特殊:主子表专属逻辑
vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue"))
.put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("api/api.ts"), .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("api/api.ts"),
vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts")) vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
// Vue3 Schema 模版 // Vue3 Schema 模版
.put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/data.ts"), .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/data.ts"),
vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts")) vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts"))
@ -149,7 +161,8 @@ public class CodegenEngine {
} }
@PostConstruct @PostConstruct
private void initGlobalBindingMap() { @VisibleForTesting
void initGlobalBindingMap() {
// 全局配置 // 全局配置
globalBindingMap.put("basePackage", codegenProperties.getBasePackage()); globalBindingMap.put("basePackage", codegenProperties.getBasePackage());
globalBindingMap.put("baseFrameworkPackage", codegenProperties.getBasePackage() globalBindingMap.put("baseFrameworkPackage", codegenProperties.getBasePackage()
@ -174,9 +187,122 @@ public class CodegenEngine {
globalBindingMap.put("DictConvertClassName", DictConvert.class.getName()); globalBindingMap.put("DictConvertClassName", DictConvert.class.getName());
globalBindingMap.put("OperateLogClassName", OperateLog.class.getName()); globalBindingMap.put("OperateLogClassName", OperateLog.class.getName());
globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.class.getName()); globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.class.getName());
globalBindingMap.put("BeanUtils", BeanUtils.class.getName());
} }
public Map<String, String> execute(CodegenTableDO table, List<CodegenColumnDO> columns) { /**
*
*
* @param table
* @param columns table
* @param subTables 使
* @param subColumnsList subTables
* @return key value
*/
public Map<String, String> execute(CodegenTableDO table, List<CodegenColumnDO> columns,
List<CodegenTableDO> subTables, List<List<CodegenColumnDO>> subColumnsList) {
// 1.1 初始化 bindMap 上下文
Map<String, Object> bindingMap = initBindingMap(table, columns, subTables, subColumnsList);
// 1.2 获得模版
Map<String, String> templates = getTemplates(table.getFrontType());
// 2. 执行生成
Map<String, String> result = Maps.newLinkedHashMapWithExpectedSize(templates.size()); // 有序
templates.forEach((vmPath, filePath) -> {
// 2.1 特殊:主子表专属逻辑
if (isSubTemplate(vmPath)) {
generateSubCode(table, subTables, result, vmPath, filePath, bindingMap);
return;
// 2.2 特殊:树表专属逻辑
} else if (isPageReqVOTemplate(vmPath)) {
// 减少多余的类生成,例如说 PageVO.java 类
if (CodegenTemplateTypeEnum.isTree(table.getTemplateType())) {
return;
}
} else if (isListReqVOTemplate(vmPath)) {
// 减少多余的类生成,例如说 ListVO.java 类
if (!CodegenTemplateTypeEnum.isTree(table.getTemplateType())) {
return;
}
}
// 2.3 默认生成
generateCode(result, vmPath, filePath, bindingMap);
});
return result;
}
private void generateCode(Map<String, String> result, String vmPath,
String filePath, Map<String, Object> bindingMap) {
filePath = formatFilePath(filePath, bindingMap);
String content = templateEngine.getTemplate(vmPath).render(bindingMap);
// 格式化代码
content = prettyCode(content);
result.put(filePath, content);
}
private void generateSubCode(CodegenTableDO table, List<CodegenTableDO> subTables,
Map<String, String> result, String vmPath,
String filePath, Map<String, Object> bindingMap) {
// 没有子表,所以不生成
if (CollUtil.isEmpty(subTables)) {
return;
}
// 主子表的模式匹配。目的:过滤掉个性化的模版
if (vmPath.contains("_normal")
&& ObjectUtil.notEqual(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_NORMAL.getType())) {
return;
}
if (vmPath.contains("_erp")
&& ObjectUtil.notEqual(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_ERP.getType())) {
return;
}
if (vmPath.contains("_inner")
&& ObjectUtil.notEqual(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_INNER.getType())) {
return;
}
// 逐个生成
for (int i = 0; i < subTables.size(); i++) {
bindingMap.put("subIndex", i);
generateCode(result, vmPath, filePath, bindingMap);
}
bindingMap.remove("subIndex");
}
/**
*
*
* vm
* Vue Pretty
*
* @param content
* @return
*/
private String prettyCode(String content) {
// Vue 界面:去除字段后面多余的 , 逗号,解决前端的 Pretty 代码格式检查的报错
content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }");
// Vue 界面:去除多的 dateFormatter只有一个的情况下说明没使用到
if (StrUtil.count(content, "dateFormatter") == 1) {
content = StrUtils.removeLineContains(content, "dateFormatter");
}
// Vue 界面:去除多的 dict 相关,只有一个的情况下,说明没使用到
if (StrUtil.count(content, "getIntDictOptions") == 1) {
content = content.replace("getIntDictOptions, ", "");
}
if (StrUtil.count(content, "getStrDictOptions") == 1) {
content = content.replace("getStrDictOptions, ", "");
}
if (StrUtil.count(content, "getBoolDictOptions") == 1) {
content = content.replace("getBoolDictOptions, ", "");
}
if (StrUtil.count(content, "DICT_TYPE.") == 0) {
content = StrUtils.removeLineContains(content, "DICT_TYPE");
}
return content;
}
private Map<String, Object> initBindingMap(CodegenTableDO table, List<CodegenColumnDO> columns,
List<CodegenTableDO> subTables, List<List<CodegenColumnDO>> subColumnsList) {
// 创建 bindingMap // 创建 bindingMap
Map<String, Object> bindingMap = new HashMap<>(globalBindingMap); Map<String, Object> bindingMap = new HashMap<>(globalBindingMap);
bindingMap.put("table", table); bindingMap.put("table", table);
@ -196,17 +322,54 @@ public class CodegenEngine {
// permission 前缀 // permission 前缀
bindingMap.put("permissionPrefix", table.getModuleName() + ":" + simpleClassNameStrikeCase); bindingMap.put("permissionPrefix", table.getModuleName() + ":" + simpleClassNameStrikeCase);
// 执行生成 // 特殊:树表专属逻辑
Map<String, String> templates = getTemplates(table.getFrontType()); if (CodegenTemplateTypeEnum.isTree(table.getTemplateType())) {
Map<String, String> result = Maps.newLinkedHashMapWithExpectedSize(templates.size()); // 有序 CodegenColumnDO treeParentColumn = CollUtil.findOne(columns,
templates.forEach((vmPath, filePath) -> { column -> Objects.equals(column.getId(), table.getTreeParentColumnId()));
filePath = formatFilePath(filePath, bindingMap); bindingMap.put("treeParentColumn", treeParentColumn);
String content = templateEngine.getTemplate(vmPath).render(bindingMap); bindingMap.put("treeParentColumn_javaField_underlineCase", toUnderlineCase(treeParentColumn.getJavaField()));
// 去除字段后面多余的 , 逗号 CodegenColumnDO treeNameColumn = CollUtil.findOne(columns,
content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }"); column -> Objects.equals(column.getId(), table.getTreeNameColumnId()));
result.put(filePath, content); bindingMap.put("treeNameColumn", treeNameColumn);
}); bindingMap.put("treeNameColumn_javaField_underlineCase", toUnderlineCase(treeNameColumn.getJavaField()));
return result; }
// 特殊:主子表专属逻辑
if (CollUtil.isNotEmpty(subTables)) {
// 创建 bindingMap
bindingMap.put("subTables", subTables);
bindingMap.put("subColumnsList", subColumnsList);
List<CodegenColumnDO> subPrimaryColumns = new ArrayList<>();
List<CodegenColumnDO> subJoinColumns = new ArrayList<>();
List<String> subJoinColumnStrikeCases = new ArrayList<>();
List<String> subSimpleClassNames = new ArrayList<>();
List<String> subClassNameVars = new ArrayList<>();
List<String> simpleClassNameUnderlineCases = new ArrayList<>();
List<String> subSimpleClassNameStrikeCases = new ArrayList<>();
for (int i = 0; i < subTables.size(); i++) {
CodegenTableDO subTable = subTables.get(i);
List<CodegenColumnDO> subColumns = subColumnsList.get(i);
subPrimaryColumns.add(CollectionUtils.findFirst(subColumns, CodegenColumnDO::getPrimaryKey)); //
CodegenColumnDO subColumn = CollectionUtils.findFirst(subColumns, // 关联的字段
column -> Objects.equals(column.getId(), subTable.getSubJoinColumnId()));
subJoinColumns.add(subColumn);
subJoinColumnStrikeCases.add(toSymbolCase(subColumn.getJavaField(), '-')); // 将 DictType 转换成 dict-type
// className 相关
String subSimpleClassName = removePrefix(subTable.getClassName(), upperFirst(subTable.getModuleName()));
subSimpleClassNames.add(subSimpleClassName);
simpleClassNameUnderlineCases.add(toUnderlineCase(subSimpleClassName)); // 将 DictType 转换成 dict_type
subClassNameVars.add(lowerFirst(subSimpleClassName)); // 将 DictType 转换成 dictType用于变量
subSimpleClassNameStrikeCases.add(toSymbolCase(subSimpleClassName, '-')); // 将 DictType 转换成 dict-type
}
bindingMap.put("subPrimaryColumns", subPrimaryColumns);
bindingMap.put("subJoinColumns", subJoinColumns);
bindingMap.put("subJoinColumn_strikeCases", subJoinColumnStrikeCases);
bindingMap.put("subSimpleClassNames", subSimpleClassNames);
bindingMap.put("simpleClassNameUnderlineCases", simpleClassNameUnderlineCases);
bindingMap.put("subClassNameVars", subClassNameVars);
bindingMap.put("subSimpleClassName_strikeCases", subSimpleClassNameStrikeCases);
}
return bindingMap;
} }
private Map<String, String> getTemplates(Integer frontType) { private Map<String, String> getTemplates(Integer frontType) {
@ -216,6 +379,7 @@ public class CodegenEngine {
return templates; return templates;
} }
@SuppressWarnings("unchecked")
private String formatFilePath(String filePath, Map<String, Object> bindingMap) { private String formatFilePath(String filePath, Map<String, Object> bindingMap) {
filePath = StrUtil.replace(filePath, "${basePackage}", filePath = StrUtil.replace(filePath, "${basePackage}",
getStr(bindingMap, "basePackage").replaceAll("\\.", "/")); getStr(bindingMap, "basePackage").replaceAll("\\.", "/"));
@ -232,6 +396,16 @@ public class CodegenEngine {
filePath = StrUtil.replace(filePath, "${table.moduleName}", table.getModuleName()); filePath = StrUtil.replace(filePath, "${table.moduleName}", table.getModuleName());
filePath = StrUtil.replace(filePath, "${table.businessName}", table.getBusinessName()); filePath = StrUtil.replace(filePath, "${table.businessName}", table.getBusinessName());
filePath = StrUtil.replace(filePath, "${table.className}", table.getClassName()); filePath = StrUtil.replace(filePath, "${table.className}", table.getClassName());
// 特殊:主子表专属逻辑
Integer subIndex = (Integer) bindingMap.get("subIndex");
if (subIndex != null) {
CodegenTableDO subTable = ((List<CodegenTableDO>) bindingMap.get("subTables")).get(subIndex);
filePath = StrUtil.replace(filePath, "${subTable.moduleName}", subTable.getModuleName());
filePath = StrUtil.replace(filePath, "${subTable.businessName}", subTable.getBusinessName());
filePath = StrUtil.replace(filePath, "${subTable.className}", subTable.getClassName());
filePath = StrUtil.replace(filePath, "${subSimpleClassName}",
((List<String>) bindingMap.get("subSimpleClassNames")).get(subIndex));
}
return filePath; return filePath;
} }
@ -298,4 +472,17 @@ public class CodegenEngine {
private static String vue3VbenTemplatePath(String path) { private static String vue3VbenTemplatePath(String path) {
return "codegen/vue3_vben/" + path + ".vm"; return "codegen/vue3_vben/" + path + ".vm";
} }
private static boolean isSubTemplate(String path) {
return path.contains("_sub");
}
private static boolean isPageReqVOTemplate(String path) {
return path.contains("pageReqVO");
}
private static boolean isListReqVOTemplate(String path) {
return path.contains("listReqVO");
}
} }

View File

@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.infra.service.demo.demo01;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactPageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactSaveReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo01.Demo01ContactDO;
import javax.validation.Valid;
/**
* Service
*
* @author
*/
public interface Demo01ContactService {
/**
*
*
* @param createReqVO
* @return
*/
Long createDemo01Contact(@Valid Demo01ContactSaveReqVO createReqVO);
/**
*
*
* @param updateReqVO
*/
void updateDemo01Contact(@Valid Demo01ContactSaveReqVO updateReqVO);
/**
*
*
* @param id
*/
void deleteDemo01Contact(Long id);
/**
*
*
* @param id
* @return
*/
Demo01ContactDO getDemo01Contact(Long id);
/**
*
*
* @param pageReqVO
* @return
*/
PageResult<Demo01ContactDO> getDemo01ContactPage(Demo01ContactPageReqVO pageReqVO);
}

View File

@ -0,0 +1,71 @@
package cn.iocoder.yudao.module.infra.service.demo.demo01;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactPageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactSaveReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo01.Demo01ContactDO;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo01.Demo01ContactMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DEMO01_CONTACT_NOT_EXISTS;
/**
* Service
*
* @author
*/
@Service
@Validated
public class Demo01ContactServiceImpl implements Demo01ContactService {
@Resource
private Demo01ContactMapper demo01ContactMapper;
@Override
public Long createDemo01Contact(Demo01ContactSaveReqVO createReqVO) {
// 插入
Demo01ContactDO demo01Contact = BeanUtils.toBean(createReqVO, Demo01ContactDO.class);
demo01ContactMapper.insert(demo01Contact);
// 返回
return demo01Contact.getId();
}
@Override
public void updateDemo01Contact(Demo01ContactSaveReqVO updateReqVO) {
// 校验存在
validateDemo01ContactExists(updateReqVO.getId());
// 更新
Demo01ContactDO updateObj = BeanUtils.toBean(updateReqVO, Demo01ContactDO.class);
demo01ContactMapper.updateById(updateObj);
}
@Override
public void deleteDemo01Contact(Long id) {
// 校验存在
validateDemo01ContactExists(id);
// 删除
demo01ContactMapper.deleteById(id);
}
private void validateDemo01ContactExists(Long id) {
if (demo01ContactMapper.selectById(id) == null) {
throw exception(DEMO01_CONTACT_NOT_EXISTS);
}
}
@Override
public Demo01ContactDO getDemo01Contact(Long id) {
return demo01ContactMapper.selectById(id);
}
@Override
public PageResult<Demo01ContactDO> getDemo01ContactPage(Demo01ContactPageReqVO pageReqVO) {
return demo01ContactMapper.selectPage(pageReqVO);
}
}

View File

@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.infra.service.demo.demo02;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryListReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategorySaveReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo02.Demo02CategoryDO;
import javax.validation.Valid;
import java.util.List;
/**
* Service
*
* @author
*/
public interface Demo02CategoryService {
/**
*
*
* @param createReqVO
* @return
*/
Long createDemo02Category(@Valid Demo02CategorySaveReqVO createReqVO);
/**
*
*
* @param updateReqVO
*/
void updateDemo02Category(@Valid Demo02CategorySaveReqVO updateReqVO);
/**
*
*
* @param id
*/
void deleteDemo02Category(Long id);
/**
*
*
* @param id
* @return
*/
Demo02CategoryDO getDemo02Category(Long id);
/**
*
*
* @param listReqVO
* @return
*/
List<Demo02CategoryDO> getDemo02CategoryList(Demo02CategoryListReqVO listReqVO);
}

View File

@ -0,0 +1,134 @@
package cn.iocoder.yudao.module.infra.service.demo.demo02;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryListReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategorySaveReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo02.Demo02CategoryDO;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo02.Demo02CategoryMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
/**
* Service
*
* @author
*/
@Service
@Validated
public class Demo02CategoryServiceImpl implements Demo02CategoryService {
@Resource
private Demo02CategoryMapper demo02CategoryMapper;
@Override
public Long createDemo02Category(Demo02CategorySaveReqVO createReqVO) {
// 校验父级编号的有效性
validateParentDemo02Category(null, createReqVO.getParentId());
// 校验名字的唯一性
validateDemo02CategoryNameUnique(null, createReqVO.getParentId(), createReqVO.getName());
// 插入
Demo02CategoryDO demo02Category = BeanUtils.toBean(createReqVO, Demo02CategoryDO.class);
demo02CategoryMapper.insert(demo02Category);
// 返回
return demo02Category.getId();
}
@Override
public void updateDemo02Category(Demo02CategorySaveReqVO updateReqVO) {
// 校验存在
validateDemo02CategoryExists(updateReqVO.getId());
// 校验父级编号的有效性
validateParentDemo02Category(updateReqVO.getId(), updateReqVO.getParentId());
// 校验名字的唯一性
validateDemo02CategoryNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
// 更新
Demo02CategoryDO updateObj = BeanUtils.toBean(updateReqVO, Demo02CategoryDO.class);
demo02CategoryMapper.updateById(updateObj);
}
@Override
public void deleteDemo02Category(Long id) {
// 校验存在
validateDemo02CategoryExists(id);
// 校验是否有子示例分类
if (demo02CategoryMapper.selectCountByParentId(id) > 0) {
throw exception(DEMO02_CATEGORY_EXITS_CHILDREN);
}
// 删除
demo02CategoryMapper.deleteById(id);
}
private void validateDemo02CategoryExists(Long id) {
if (demo02CategoryMapper.selectById(id) == null) {
throw exception(DEMO02_CATEGORY_NOT_EXISTS);
}
}
private void validateParentDemo02Category(Long id, Long parentId) {
if (parentId == null || Demo02CategoryDO.PARENT_ID_ROOT.equals(parentId)) {
return;
}
// 1. 不能设置自己为父示例分类
if (Objects.equals(id, parentId)) {
throw exception(DEMO02_CATEGORY_PARENT_ERROR);
}
// 2. 父示例分类不存在
Demo02CategoryDO parentDemo02Category = demo02CategoryMapper.selectById(parentId);
if (parentDemo02Category == null) {
throw exception(DEMO02_CATEGORY_PARENT_NOT_EXITS);
}
// 3. 递归校验父示例分类,如果父示例分类是自己的子示例分类,则报错,避免形成环路
if (id == null) { // id 为空,说明新增,不需要考虑环路
return;
}
for (int i = 0; i < Short.MAX_VALUE; i++) {
// 3.1 校验环路
parentId = parentDemo02Category.getParentId();
if (Objects.equals(id, parentId)) {
throw exception(DEMO02_CATEGORY_PARENT_IS_CHILD);
}
// 3.2 继续递归下一级父示例分类
if (parentId == null || Demo02CategoryDO.PARENT_ID_ROOT.equals(parentId)) {
break;
}
parentDemo02Category = demo02CategoryMapper.selectById(parentId);
if (parentDemo02Category == null) {
break;
}
}
}
private void validateDemo02CategoryNameUnique(Long id, Long parentId, String name) {
Demo02CategoryDO demo02Category = demo02CategoryMapper.selectByParentIdAndName(parentId, name);
if (demo02Category == null) {
return;
}
// 如果 id 为空,说明不用比较是否为相同 id 的示例分类
if (id == null) {
throw exception(DEMO02_CATEGORY_NAME_DUPLICATE);
}
if (!Objects.equals(demo02Category.getId(), id)) {
throw exception(DEMO02_CATEGORY_NAME_DUPLICATE);
}
}
@Override
public Demo02CategoryDO getDemo02Category(Long id) {
return demo02CategoryMapper.selectById(id);
}
@Override
public List<Demo02CategoryDO> getDemo02CategoryList(Demo02CategoryListReqVO listReqVO) {
return demo02CategoryMapper.selectList(listReqVO);
}
}

View File

@ -0,0 +1,158 @@
package cn.iocoder.yudao.module.infra.service.demo.demo03;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentSaveReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
import javax.validation.Valid;
import java.util.List;
/**
* Service
*
* @author
*/
public interface Demo03StudentService {
/**
*
*
* @param createReqVO
* @return
*/
Long createDemo03Student(@Valid Demo03StudentSaveReqVO createReqVO);
/**
*
*
* @param updateReqVO
*/
void updateDemo03Student(@Valid Demo03StudentSaveReqVO updateReqVO);
/**
*
*
* @param id
*/
void deleteDemo03Student(Long id);
/**
*
*
* @param id
* @return
*/
Demo03StudentDO getDemo03Student(Long id);
/**
*
*
* @param pageReqVO
* @return
*/
PageResult<Demo03StudentDO> getDemo03StudentPage(Demo03StudentPageReqVO pageReqVO);
// ==================== 子表(学生课程) ====================
/**
*
*
* @param studentId
* @return
*/
List<Demo03CourseDO> getDemo03CourseListByStudentId(Long studentId);
/**
*
*
* @param pageReqVO
* @param studentId
* @return
*/
PageResult<Demo03CourseDO> getDemo03CoursePage(PageParam pageReqVO, Long studentId);
/**
*
*
* @param demo03Course
* @return
*/
Long createDemo03Course(@Valid Demo03CourseDO demo03Course);
/**
*
*
* @param demo03Course
*/
void updateDemo03Course(@Valid Demo03CourseDO demo03Course);
/**
*
*
* @param id
*/
void deleteDemo03Course(Long id);
/**
*
*
* @param id
* @return
*/
Demo03CourseDO getDemo03Course(Long id);
// ==================== 子表(学生班级) ====================
/**
*
*
* @param studentId
* @return
*/
Demo03GradeDO getDemo03GradeByStudentId(Long studentId);
/**
*
*
* @param pageReqVO
* @param studentId
* @return
*/
PageResult<Demo03GradeDO> getDemo03GradePage(PageParam pageReqVO, Long studentId);
/**
*
*
* @param demo03Grade
* @return
*/
Long createDemo03Grade(@Valid Demo03GradeDO demo03Grade);
/**
*
*
* @param demo03Grade
*/
void updateDemo03Grade(@Valid Demo03GradeDO demo03Grade);
/**
*
*
* @param id
*/
void deleteDemo03Grade(Long id);
/**
*
*
* @param id
* @return
*/
Demo03GradeDO getDemo03Grade(Long id);
}

View File

@ -0,0 +1,217 @@
package cn.iocoder.yudao.module.infra.service.demo.demo03;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentSaveReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.Demo03CourseMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.Demo03GradeMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.Demo03StudentMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
/**
* Service
*
* @author
*/
@Service
@Validated
public class Demo03StudentServiceImpl implements Demo03StudentService {
@Resource
private Demo03StudentMapper demo03StudentMapper;
@Resource
private Demo03CourseMapper demo03CourseMapper;
@Resource
private Demo03GradeMapper demo03GradeMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createDemo03Student(Demo03StudentSaveReqVO createReqVO) {
// 插入
Demo03StudentDO demo03Student = BeanUtils.toBean(createReqVO, Demo03StudentDO.class);
demo03StudentMapper.insert(demo03Student);
// 插入子表
createDemo03CourseList(demo03Student.getId(), createReqVO.getDemo03Courses());
createDemo03Grade(demo03Student.getId(), createReqVO.getDemo03Grade());
// 返回
return demo03Student.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateDemo03Student(Demo03StudentSaveReqVO updateReqVO) {
// 校验存在
validateDemo03StudentExists(updateReqVO.getId());
// 更新
Demo03StudentDO updateObj = BeanUtils.toBean(updateReqVO, Demo03StudentDO.class);
demo03StudentMapper.updateById(updateObj);
// 更新子表
updateDemo03CourseList(updateReqVO.getId(), updateReqVO.getDemo03Courses());
updateDemo03Grade(updateReqVO.getId(), updateReqVO.getDemo03Grade());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteDemo03Student(Long id) {
// 校验存在
validateDemo03StudentExists(id);
// 删除
demo03StudentMapper.deleteById(id);
// 删除子表
deleteDemo03CourseByStudentId(id);
deleteDemo03GradeByStudentId(id);
}
private void validateDemo03StudentExists(Long id) {
if (demo03StudentMapper.selectById(id) == null) {
throw exception(DEMO03_STUDENT_NOT_EXISTS);
}
}
@Override
public Demo03StudentDO getDemo03Student(Long id) {
return demo03StudentMapper.selectById(id);
}
@Override
public PageResult<Demo03StudentDO> getDemo03StudentPage(Demo03StudentPageReqVO pageReqVO) {
return demo03StudentMapper.selectPage(pageReqVO);
}
// ==================== 子表(学生课程) ====================
@Override
public List<Demo03CourseDO> getDemo03CourseListByStudentId(Long studentId) {
return demo03CourseMapper.selectListByStudentId(studentId);
}
private void createDemo03CourseList(Long studentId, List<Demo03CourseDO> list) {
if (list != null) {
list.forEach(o -> o.setStudentId(studentId));
}
demo03CourseMapper.insertBatch(list);
}
private void updateDemo03CourseList(Long studentId, List<Demo03CourseDO> list) {
deleteDemo03CourseByStudentId(studentId);
list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下1id 冲突2updateTime 不更新
createDemo03CourseList(studentId, list);
}
private void deleteDemo03CourseByStudentId(Long studentId) {
demo03CourseMapper.deleteByStudentId(studentId);
}
@Override
public PageResult<Demo03CourseDO> getDemo03CoursePage(PageParam pageReqVO, Long studentId) {
return demo03CourseMapper.selectPage(pageReqVO, studentId);
}
@Override
public Long createDemo03Course(Demo03CourseDO demo03Course) {
demo03CourseMapper.insert(demo03Course);
return demo03Course.getId();
}
@Override
public void updateDemo03Course(Demo03CourseDO demo03Course) {
demo03CourseMapper.updateById(demo03Course);
}
@Override
public void deleteDemo03Course(Long id) {
demo03CourseMapper.deleteById(id);
}
@Override
public Demo03CourseDO getDemo03Course(Long id) {
return demo03CourseMapper.selectById(id);
}
// ==================== 子表(学生班级) ====================
@Override
public Demo03GradeDO getDemo03GradeByStudentId(Long studentId) {
return demo03GradeMapper.selectByStudentId(studentId);
}
private void createDemo03Grade(Long studentId, Demo03GradeDO demo03Grade) {
if (demo03Grade == null) {
return;
}
demo03Grade.setStudentId(studentId);
demo03GradeMapper.insert(demo03Grade);
}
private void updateDemo03Grade(Long studentId, Demo03GradeDO demo03Grade) {
if (demo03Grade == null) {
return;
}
demo03Grade.setStudentId(studentId);
demo03Grade.setUpdater(null).setUpdateTime(null); // 解决更新情况下updateTime 不更新
demo03GradeMapper.insertOrUpdate(demo03Grade);
}
private void deleteDemo03GradeByStudentId(Long studentId) {
demo03GradeMapper.deleteByStudentId(studentId);
}
@Override
public PageResult<Demo03GradeDO> getDemo03GradePage(PageParam pageReqVO, Long studentId) {
return demo03GradeMapper.selectPage(pageReqVO, studentId);
}
@Override
public Long createDemo03Grade(Demo03GradeDO demo03Grade) {
// 校验是否已经存在
if (demo03GradeMapper.selectByStudentId(demo03Grade.getStudentId()) != null) {
throw exception(DEMO03_GRADE_EXISTS);
}
demo03GradeMapper.insert(demo03Grade);
return demo03Grade.getId();
}
@Override
public void updateDemo03Grade(Demo03GradeDO demo03Grade) {
// 校验存在
validateDemo03GradeExists(demo03Grade.getId());
// 更新
demo03GradeMapper.updateById(demo03Grade);
}
@Override
public void deleteDemo03Grade(Long id) {
// 校验存在
validateDemo03GradeExists(id);
// 删除
demo03GradeMapper.deleteById(id);
}
@Override
public Demo03GradeDO getDemo03Grade(Long id) {
return demo03GradeMapper.selectById(id);
}
private void validateDemo03GradeExists(Long id) {
if (demo03GradeMapper.selectById(id) == null) {
throw exception(DEMO03_GRADE_NOT_EXISTS);
}
}
}

View File

@ -1,75 +0,0 @@
package cn.iocoder.yudao.module.infra.service.test;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoCreateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoExportReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoPageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoUpdateReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
* Service
*
* @author
*/
public interface TestDemoService {
/**
*
*
* @param createReqVO
* @return
*/
Long createTestDemo(@Valid TestDemoCreateReqVO createReqVO);
/**
*
*
* @param updateReqVO
*/
void updateTestDemo(@Valid TestDemoUpdateReqVO updateReqVO);
/**
*
*
* @param id
*/
void deleteTestDemo(Long id);
/**
*
*
* @param id
* @return
*/
TestDemoDO getTestDemo(Long id);
/**
*
*
* @param ids
* @return
*/
List<TestDemoDO> getTestDemoList(Collection<Long> ids);
/**
*
*
* @param pageReqVO
* @return
*/
PageResult<TestDemoDO> getTestDemoPage(TestDemoPageReqVO pageReqVO);
/**
* , Excel
*
* @param exportReqVO
* @return
*/
List<TestDemoDO> getTestDemoList(TestDemoExportReqVO exportReqVO);
}

View File

@ -1,91 +0,0 @@
package cn.iocoder.yudao.module.infra.service.test;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoCreateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoExportReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoPageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoUpdateReqVO;
import cn.iocoder.yudao.module.infra.convert.test.TestDemoConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO;
import cn.iocoder.yudao.module.infra.dal.mysql.test.TestDemoMapper;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.TEST_DEMO_NOT_EXISTS;
/**
* Service
*
* @author
*/
@Service
@Validated
public class TestDemoServiceImpl implements TestDemoService {
@Resource
private TestDemoMapper testDemoMapper;
@Override
public Long createTestDemo(TestDemoCreateReqVO createReqVO) {
// 插入
TestDemoDO testDemo = TestDemoConvert.INSTANCE.convert(createReqVO);
testDemoMapper.insert(testDemo);
// 返回
return testDemo.getId();
}
@Override
@CacheEvict(value = "test", key = "#updateReqVO.id")
public void updateTestDemo(TestDemoUpdateReqVO updateReqVO) {
// 校验存在
validateTestDemoExists(updateReqVO.getId());
// 更新
TestDemoDO updateObj = TestDemoConvert.INSTANCE.convert(updateReqVO);
testDemoMapper.updateById(updateObj);
}
@Override
@CacheEvict(value = "test", key = "#id")
public void deleteTestDemo(Long id) {
// 校验存在
validateTestDemoExists(id);
// 删除
testDemoMapper.deleteById(id);
}
private void validateTestDemoExists(Long id) {
if (testDemoMapper.selectById(id) == null) {
throw exception(TEST_DEMO_NOT_EXISTS);
}
}
@Override
@Cacheable(cacheNames = "test", key = "#id")
public TestDemoDO getTestDemo(Long id) {
return testDemoMapper.selectById(id);
}
@Override
public List<TestDemoDO> getTestDemoList(Collection<Long> ids) {
return testDemoMapper.selectBatchIds(ids);
}
@Override
public PageResult<TestDemoDO> getTestDemoPage(TestDemoPageReqVO pageReqVO) {
// testDemoMapper.selectList2();
return testDemoMapper.selectPage(pageReqVO);
}
@Override
public List<TestDemoDO> getTestDemoList(TestDemoExportReqVO exportReqVO) {
return testDemoMapper.selectList(exportReqVO);
}
}

View File

@ -15,8 +15,10 @@ import javax.servlet.http.*;
import java.util.*; import java.util.*;
import java.io.IOException; import java.io.IOException;
import ${PageParamClassName};
import ${PageResultClassName}; import ${PageResultClassName};
import ${CommonResultClassName}; import ${CommonResultClassName};
import ${BeanUtils};
import static ${CommonResultClassName}.success; import static ${CommonResultClassName}.success;
import ${ExcelUtilsClassName}; import ${ExcelUtilsClassName};
@ -26,7 +28,10 @@ import static ${OperateTypeEnumClassName}.*;
import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*;
import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO;
import ${basePackage}.module.${table.moduleName}.convert.${table.businessName}.${table.className}Convert; ## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO;
#end
import ${basePackage}.module.${table.moduleName}.service.${table.businessName}.${table.className}Service; import ${basePackage}.module.${table.moduleName}.service.${table.businessName}.${table.className}Service;
@Tag(name = "${sceneEnum.name} - ${table.classComment}") @Tag(name = "${sceneEnum.name} - ${table.classComment}")
@ -41,17 +46,19 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建${table.classComment}") @Operation(summary = "创建${table.classComment}")
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')")#end #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')")
public CommonResult<${primaryColumn.javaType}> create${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO) { #end
public CommonResult<${primaryColumn.javaType}> create${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO) {
return success(${classNameVar}Service.create${simpleClassName}(createReqVO)); return success(${classNameVar}Service.create${simpleClassName}(createReqVO));
} }
@PutMapping("/update") @PutMapping("/update")
@Operation(summary = "更新${table.classComment}") @Operation(summary = "更新${table.classComment}")
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')")#end #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')")
public CommonResult<Boolean> update${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO) { #end
public CommonResult<Boolean> update${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO) {
${classNameVar}Service.update${simpleClassName}(updateReqVO); ${classNameVar}Service.update${simpleClassName}(updateReqVO);
return success(true); return success(true);
} }
@ -59,8 +66,9 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
@DeleteMapping("/delete") @DeleteMapping("/delete")
@Operation(summary = "删除${table.classComment}") @Operation(summary = "删除${table.classComment}")
@Parameter(name = "id", description = "编号", required = true) @Parameter(name = "id", description = "编号", required = true)
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')")#end #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')")
#end
public CommonResult<Boolean> delete${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) { public CommonResult<Boolean> delete${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) {
${classNameVar}Service.delete${simpleClassName}(id); ${classNameVar}Service.delete${simpleClassName}(id);
return success(true); return success(true);
@ -69,43 +77,157 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
@GetMapping("/get") @GetMapping("/get")
@Operation(summary = "获得${table.classComment}") @Operation(summary = "获得${table.classComment}")
@Parameter(name = "id", description = "编号", required = true, example = "1024") @Parameter(name = "id", description = "编号", required = true, example = "1024")
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")#end #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
#end
public CommonResult<${sceneEnum.prefixClass}${table.className}RespVO> get${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) { public CommonResult<${sceneEnum.prefixClass}${table.className}RespVO> get${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) {
${table.className}DO ${classNameVar} = ${classNameVar}Service.get${simpleClassName}(id); ${table.className}DO ${classNameVar} = ${classNameVar}Service.get${simpleClassName}(id);
return success(${table.className}Convert.INSTANCE.convert(${classNameVar})); return success(BeanUtils.toBean(${classNameVar}, ${sceneEnum.prefixClass}${table.className}RespVO.class));
}
@GetMapping("/list")
@Operation(summary = "获得${table.classComment}列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")#end
public CommonResult<List<${sceneEnum.prefixClass}${table.className}RespVO>> get${simpleClassName}List(@RequestParam("ids") Collection<${primaryColumn.javaType}> ids) {
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(ids);
return success(${table.className}Convert.INSTANCE.convertList(list));
} }
#if ( $table.templateType != 2 )
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得${table.classComment}分页") @Operation(summary = "获得${table.classComment}分页")
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")#end #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
public CommonResult<PageResult<${sceneEnum.prefixClass}${table.className}RespVO>> get${simpleClassName}Page(@Valid ${sceneEnum.prefixClass}${table.className}PageReqVO pageVO) { #end
PageResult<${table.className}DO> pageResult = ${classNameVar}Service.get${simpleClassName}Page(pageVO); public CommonResult<PageResult<${sceneEnum.prefixClass}${table.className}RespVO>> get${simpleClassName}Page(@Valid ${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO) {
return success(${table.className}Convert.INSTANCE.convertPage(pageResult)); PageResult<${table.className}DO> pageResult = ${classNameVar}Service.get${simpleClassName}Page(pageReqVO);
return success(BeanUtils.toBean(pageResult, ${sceneEnum.prefixClass}${table.className}RespVO.class));
} }
## 特殊:树表专属逻辑(树不需要分页接口)
#else
@GetMapping("/list")
@Operation(summary = "获得${table.classComment}列表")
#if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
#end
public CommonResult<List<${sceneEnum.prefixClass}${table.className}RespVO>> get${simpleClassName}List(@Valid ${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO) {
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(listReqVO);
return success(BeanUtils.toBean(list, ${sceneEnum.prefixClass}${table.className}RespVO.class));
}
#end
@GetMapping("/export-excel") @GetMapping("/export-excel")
@Operation(summary = "导出${table.classComment} Excel") @Operation(summary = "导出${table.classComment} Excel")
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:export')")#end #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:export')")
#end
@OperateLog(type = EXPORT) @OperateLog(type = EXPORT)
public void export${simpleClassName}Excel(@Valid ${sceneEnum.prefixClass}${table.className}ExportReqVO exportReqVO, #if ( $table.templateType != 2 )
public void export${simpleClassName}Excel(@Valid ${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO,
HttpServletResponse response) throws IOException { HttpServletResponse response) throws IOException {
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(exportReqVO); pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}Page(pageReqVO).getList();
// 导出 Excel // 导出 Excel
List<${sceneEnum.prefixClass}${table.className}ExcelVO> datas = ${table.className}Convert.INSTANCE.convertList02(list); ExcelUtils.write(response, "${table.classComment}.xls", "数据", ${table.className}RespVO.class,
ExcelUtils.write(response, "${table.classComment}.xls", "数据", ${sceneEnum.prefixClass}${table.className}ExcelVO.class, datas); BeanUtils.toBean(list, ${table.className}RespVO.class));
}
## 特殊:树表专属逻辑(树不需要分页接口)
#else
public void export${simpleClassName}Excel(@Valid ${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO,
HttpServletResponse response) throws IOException {
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(listReqVO);
// 导出 Excel
ExcelUtils.write(response, "${table.classComment}.xls", "数据", ${table.className}RespVO.class,
BeanUtils.toBean(list, ${table.className}RespVO.class));
}
#end
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
#set ($subClassNameVar = $subClassNameVars.get($index))
// ==================== 子表($subTable.classComment ====================
## 情况一MASTER_ERP 时,需要分查询页子表
#if ( $table.templateType == 11 )
@GetMapping("/${subSimpleClassName_strikeCase}/page")
@Operation(summary = "获得${subTable.classComment}分页")
@Parameter(name = "${subJoinColumn.javaField}", description = "${subJoinColumn.columnComment}")
#if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
#end
public CommonResult<PageResult<${subTable.className}DO>> get${subSimpleClassName}Page(PageParam pageReqVO,
@RequestParam("${subJoinColumn.javaField}") ${subJoinColumn.javaType} ${subJoinColumn.javaField}) {
return success(${classNameVar}Service.get${subSimpleClassName}Page(pageReqVO, ${subJoinColumn.javaField}));
} }
## 情况二:非 MASTER_ERP 时,需要列表查询子表
#else
#if ( $subTable.subJoinMany )
@GetMapping("/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}")
@Operation(summary = "获得${subTable.classComment}列表")
@Parameter(name = "${subJoinColumn.javaField}", description = "${subJoinColumn.columnComment}")
#if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
#end
public CommonResult<List<${subTable.className}DO>> get${subSimpleClassName}ListBy${SubJoinColumnName}(@RequestParam("${subJoinColumn.javaField}") ${subJoinColumn.javaType} ${subJoinColumn.javaField}) {
return success(${classNameVar}Service.get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}));
}
#else
@GetMapping("/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}")
@Operation(summary = "获得${subTable.classComment}")
@Parameter(name = "${subJoinColumn.javaField}", description = "${subJoinColumn.columnComment}")
#if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
#end
public CommonResult<${subTable.className}DO> get${subSimpleClassName}By${SubJoinColumnName}(@RequestParam("${subJoinColumn.javaField}") ${subJoinColumn.javaType} ${subJoinColumn.javaField}) {
return success(${classNameVar}Service.get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}));
}
#end
#end
## 特殊MASTER_ERP 时,支持单个的新增、修改、删除操作
#if ( $table.templateType == 11 )
@PostMapping("/${subSimpleClassName_strikeCase}/create")
@Operation(summary = "创建${subTable.classComment}")
#if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')")
#end
public CommonResult<${subPrimaryColumn.javaType}> create${subSimpleClassName}(@Valid @RequestBody ${subTable.className}DO ${subClassNameVar}) {
return success(${classNameVar}Service.create${subSimpleClassName}(${subClassNameVar}));
}
@PutMapping("/${subSimpleClassName_strikeCase}/update")
@Operation(summary = "更新${subTable.classComment}")
#if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')")
#end
public CommonResult<Boolean> update${subSimpleClassName}(@Valid @RequestBody ${subTable.className}DO ${subClassNameVar}) {
${classNameVar}Service.update${subSimpleClassName}(${subClassNameVar});
return success(true);
}
@DeleteMapping("/${subSimpleClassName_strikeCase}/delete")
@Parameter(name = "id", description = "编号", required = true)
@Operation(summary = "删除${subTable.classComment}")
#if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')")
#end
public CommonResult<Boolean> delete${subSimpleClassName}(@RequestParam("id") ${subPrimaryColumn.javaType} id) {
${classNameVar}Service.delete${subSimpleClassName}(id);
return success(true);
}
@GetMapping("/${subSimpleClassName_strikeCase}/get")
@Operation(summary = "获得${subTable.classComment}")
@Parameter(name = "id", description = "编号", required = true)
#if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
#end
public CommonResult<${subTable.className}DO> get${subSimpleClassName}(@RequestParam("id") ${subPrimaryColumn.javaType} id) {
return success(${classNameVar}Service.get${subSimpleClassName}(id));
}
#end
#end
} }

View File

@ -1,13 +0,0 @@
## 提供给 baseVO、createVO、updateVO 生成字段
@Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end)
#if (!${column.nullable})## 判断 @NotEmpty 和 @NotNull 注解
#if (${field.fieldType} == 'String')
@NotEmpty(message = "${column.columnComment}不能为空")
#else
@NotNull(message = "${column.columnComment}不能为空")
#end
#end
#if (${column.javaType} == "LocalDateTime")## 时间类型
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
#end
private ${column.javaType} ${column.javaField};

View File

@ -1,39 +0,0 @@
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
#foreach ($column in $columns)
#if (${column.javaType} == "BigDecimal")
import java.math.BigDecimal;
#end
#if (${column.javaType} == "LocalDateTime")
import java.time.LocalDateTime;
#end
#end
import javax.validation.constraints.*;
## 处理 Date 字段的引入
#foreach ($column in $columns)
#if (${column.createOperation} && ${column.updateOperation} && ${column.listOperationResult}
&& ${column.javaType} == "LocalDateTime")## 时间类型
import org.springframework.format.annotation.DateTimeFormat;
import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
#break
#end
#end
/**
* ${table.classComment} Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class ${sceneEnum.prefixClass}${table.className}BaseVO {
#foreach ($column in $columns)
#if (${column.createOperation} && ${column.updateOperation} && ${column.listOperationResult})##通用操作
#parse("codegen/java/controller/vo/_column.vm")
#end
#end
}

View File

@ -1,30 +0,0 @@
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.*;
## 处理 Date 字段的引入
#foreach ($column in $columns)
#if (${column.createOperation} && (!${column.updateOperation} || !${column.listOperationResult})
&& ${column.javaType} == "LocalDateTime")## 时间类型
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
#break
#end
#end
@Schema(description = "${sceneEnum.name} - ${table.classComment}创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ${sceneEnum.prefixClass}${table.className}CreateReqVO extends ${sceneEnum.prefixClass}${table.className}BaseVO {
#foreach ($column in $columns)
#if (${column.createOperation} && (!${column.updateOperation} || !${column.listOperationResult}))##不是通用字段
#parse("codegen/java/controller/vo/_column.vm")
#end
#end
}

View File

@ -1,45 +0,0 @@
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
#foreach ($column in $columns)
#if (${column.javaType} == "BigDecimal")
import java.math.BigDecimal;
#end
#if (${column.javaType} == "LocalDateTime")
import java.time.LocalDateTime;
#end
#end
import com.alibaba.excel.annotation.ExcelProperty;
#foreach ($column in $columns)
#if ("$!column.dictType" != "")## 有设置数据字典
import ${DictFormatClassName};
import ${DictConvertClassName};
#break
#end
#end
/**
* ${table.classComment} Excel VO
*
* @author ${table.author}
*/
@Data
public class ${sceneEnum.prefixClass}${table.className}ExcelVO {
#foreach ($column in $columns)
#if (${column.listOperationResult})##返回字段
#if ("$!column.dictType" != "")##处理枚举值
@ExcelProperty(value = "${column.columnComment}", converter = DictConvert.class)
@DictFormat("${column.dictType}") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
#else
@ExcelProperty("${column.columnComment}")
#end
private ${column.javaType} ${column.javaField};
#end
#end
}

View File

@ -4,9 +4,15 @@ import lombok.*;
import java.util.*; import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import ${PageParamClassName}; import ${PageParamClassName};
## 处理 Date 字段的引入
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.listOperation} && ${column.javaType} == "LocalDateTime")## 时间类型 #if (${column.javaType} == "BigDecimal")
import java.math.BigDecimal;
#break
#end
#end
## 处理 LocalDateTime 字段的引入
#foreach ($column in $columns)
#if (${column.listOperation} && ${column.javaType} == "LocalDateTime")
import java.time.LocalDateTime; import java.time.LocalDateTime;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
@ -20,9 +26,9 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
private ${column.javaType}#if ("$!prefix" != "") ${prefix}${JavaField}#else ${column.javaField}#end; private ${column.javaType}#if ("$!prefix" != "") ${prefix}${JavaField}#else ${column.javaField}#end;
#end #end
@Schema(description = "${sceneEnum.name} - ${table.classComment} Excel 导出 Request VO参数和 ${table.className}PageReqVO 是一致的") @Schema(description = "${sceneEnum.name} - ${table.classComment}列表 Request VO")
@Data @Data
public class ${sceneEnum.prefixClass}${table.className}ExportReqVO { public class ${sceneEnum.prefixClass}${table.className}ListReqVO {
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.listOperation})##查询操作 #if (${column.listOperation})##查询操作

View File

@ -4,9 +4,15 @@ import lombok.*;
import java.util.*; import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import ${PageParamClassName}; import ${PageParamClassName};
## 处理 Date 字段的引入
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.listOperation} && ${column.javaType} == "LocalDateTime")## 时间类型 #if (${column.javaType} == "BigDecimal")
import java.math.BigDecimal;
#break
#end
#end
## 处理 LocalDateTime 字段的引入
#foreach ($column in $columns)
#if (${column.listOperationCondition} && ${column.javaType} == "LocalDateTime")
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;

View File

@ -2,22 +2,51 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePac
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import java.util.*;
## 处理 BigDecimal 字段的引入
import java.util.*;
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.javaType} == "LocalDateTime") #if (${column.javaType} == "BigDecimal")
import java.math.BigDecimal;
#break
#end
#end
## 处理 LocalDateTime 字段的引入
#foreach ($column in $columns)
#if (${column.listOperationResult} && ${column.javaType} == "LocalDateTime")
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
#break #break
#end #end
#end #end
## 处理 Excel 导出
import com.alibaba.excel.annotation.*;
#foreach ($column in $columns)
#if ("$!column.dictType" != "")## 有设置数据字典
import ${DictFormatClassName};
import ${DictConvertClassName};
#break
#end
#end
@Schema(description = "${sceneEnum.name} - ${table.classComment} Response VO") @Schema(description = "${sceneEnum.name} - ${table.classComment} Response VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @ExcelIgnoreUnannotated
@ToString(callSuper = true) public class ${sceneEnum.prefixClass}${table.className}RespVO {
public class ${sceneEnum.prefixClass}${table.className}RespVO extends ${sceneEnum.prefixClass}${table.className}BaseVO {
## 逐个处理字段
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.listOperationResult} && (!${column.createOperation} || !${column.updateOperation}))##不是通用字段 #if (${column.listOperationResult})
## 1. 处理 Swagger 注解
@Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end) @Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end)
## 2. 处理 Excel 导出
#if ("$!column.dictType" != "")##处理枚举值
@ExcelProperty(value = "${column.columnComment}", converter = DictConvert.class)
@DictFormat("${column.dictType}") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
#else
@ExcelProperty("${column.columnComment}")
#end
## 3. 处理字段定义
private ${column.javaType} ${column.javaField}; private ${column.javaType} ${column.javaField};
#end #end

View File

@ -0,0 +1,65 @@
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
## 处理 BigDecimal 字段的引入
import java.util.*;
#foreach ($column in $columns)
#if (${column.javaType} == "BigDecimal")
import java.math.BigDecimal;
#break
#end
#end
## 处理 LocalDateTime 字段的引入
#foreach ($column in $columns)
#if ((${column.createOperation} || ${column.updateOperation}) && ${column.javaType} == "LocalDateTime")
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
#break
#end
#end
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO;
#end
@Schema(description = "${sceneEnum.name} - ${table.classComment}新增/修改 Request VO")
@Data
public class ${sceneEnum.prefixClass}${table.className}SaveReqVO {
## 逐个处理字段
#foreach ($column in $columns)
#if (${column.createOperation} || ${column.updateOperation})
## 1. 处理 Swagger 注解
@Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end)
## 2. 处理 Validator 参数校验
#if (!${column.nullable} && !${column.primaryKey})
#if (${column.javaType} == 'String')
@NotEmpty(message = "${column.columnComment}不能为空")
#else
@NotNull(message = "${column.columnComment}不能为空")
#end
#end
## 3. 处理字段定义
private ${column.javaType} ${column.javaField};
#end
#end
## 特殊:主子表专属逻辑(非 ERP 模式)
#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#if ( $subTable.subJoinMany)
@Schema(description = "${subTable.classComment}列表")
private List<${subTable.className}DO> ${subClassNameVars.get($index)}s;
#else
@Schema(description = "${subTable.classComment}")
private ${subTable.className}DO ${subClassNameVars.get($index)};
#end
#end
#end
}

View File

@ -1,30 +0,0 @@
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
## 处理 Date 字段的引入
#foreach ($column in $columns)
#if (${column.updateOperation} && (!${column.createOperation} || !${column.listOperationResult})
&& ${column.javaType} == "LocalDateTime")## 时间类型
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
#break
#end
#end
@Schema(description = "${sceneEnum.name} - ${table.classComment}更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ${sceneEnum.prefixClass}${table.className}UpdateReqVO extends ${sceneEnum.prefixClass}${table.className}BaseVO {
#foreach ($column in $columns)
#if (${column.updateOperation} && (!${column.createOperation} || !${column.listOperationResult}))##不是通用字段
#parse("codegen/java/controller/vo/_column.vm")
#end
#end
}

View File

@ -1,34 +0,0 @@
package ${basePackage}.module.${table.moduleName}.convert.${table.businessName};
import java.util.*;
import ${PageResultClassName};
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*;
import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO;
/**
* ${table.classComment} Convert
*
* @author ${table.author}
*/
@Mapper
public interface ${table.className}Convert {
${table.className}Convert INSTANCE = Mappers.getMapper(${table.className}Convert.class);
${table.className}DO convert(${sceneEnum.prefixClass}${table.className}CreateReqVO bean);
${table.className}DO convert(${sceneEnum.prefixClass}${table.className}UpdateReqVO bean);
${sceneEnum.prefixClass}${table.className}RespVO convert(${table.className}DO bean);
List<${sceneEnum.prefixClass}${table.className}RespVO> convertList(List<${table.className}DO> list);
PageResult<${sceneEnum.prefixClass}${table.className}RespVO> convertPage(PageResult<${table.className}DO> page);
List<${sceneEnum.prefixClass}${table.className}ExcelVO> convertList02(List<${table.className}DO> list);
}

View File

@ -28,6 +28,11 @@ import ${BaseDOClassName};
@AllArgsConstructor @AllArgsConstructor
public class ${table.className}DO extends BaseDO { public class ${table.className}DO extends BaseDO {
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
public static final Long ${treeParentColumn_javaField_underlineCase.toUpperCase()}_ROOT = 0L;
#end
#foreach ($column in $columns) #foreach ($column in $columns)
#if (!${baseDOFields.contains(${column.javaField})})##排除 BaseDO 的字段 #if (!${baseDOFields.contains(${column.javaField})})##排除 BaseDO 的字段
/** /**

View File

@ -0,0 +1,49 @@
#set ($subTable = $subTables.get($subIndex))##当前表
#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
package ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName};
import lombok.*;
import java.util.*;
#foreach ($column in $subColumns)
#if (${column.javaType} == "BigDecimal")
import java.math.BigDecimal;
#end
#if (${column.javaType} == "LocalDateTime")
import java.time.LocalDateTime;
#end
#end
import com.baomidou.mybatisplus.annotation.*;
import ${BaseDOClassName};
/**
* ${subTable.classComment} DO
*
* @author ${subTable.author}
*/
@TableName("${subTable.tableName.toLowerCase()}")
@KeySequence("${subTable.tableName.toLowerCase()}_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ${subTable.className}DO extends BaseDO {
#foreach ($column in $subColumns)
#if (!${baseDOFields.contains(${column.javaField})})##排除 BaseDO 的字段
/**
* ${column.columnComment}
#if ("$!column.dictType" != "")##处理枚举值
*
* 枚举 {@link TODO ${column.dictType} 对应的类}
#end
*/
#if (${column.primaryKey})##处理主键
@TableId#if (${column.javaType} == 'String')(type = IdType.INPUT)#end
#end
private ${column.javaType} ${column.javaField};
#end
#end
}

View File

@ -49,18 +49,34 @@ import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePack
@Mapper @Mapper
public interface ${table.className}Mapper extends BaseMapperX<${table.className}DO> { public interface ${table.className}Mapper extends BaseMapperX<${table.className}DO> {
## 特殊:树表专属逻辑(树不需要分页接口)
#if ( $table.templateType != 2 )
default PageResult<${table.className}DO> selectPage(${sceneEnum.prefixClass}${table.className}PageReqVO reqVO) { default PageResult<${table.className}DO> selectPage(${sceneEnum.prefixClass}${table.className}PageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<${table.className}DO>() return selectPage(reqVO, new LambdaQueryWrapperX<${table.className}DO>()
#listCondition() #listCondition()
.orderByDesc(${table.className}DO::getId));## 大多数情况下id 倒序 .orderByDesc(${table.className}DO::getId));## 大多数情况下id 倒序
} }
#else
default List<${table.className}DO> selectList(${sceneEnum.prefixClass}${table.className}ExportReqVO reqVO) { default List<${table.className}DO> selectList(${sceneEnum.prefixClass}${table.className}ListReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<${table.className}DO>() return selectList(new LambdaQueryWrapperX<${table.className}DO>()
#listCondition() #listCondition()
.orderByDesc(${table.className}DO::getId));## 大多数情况下id 倒序 .orderByDesc(${table.className}DO::getId));## 大多数情况下id 倒序
} }
#end
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写
#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写
default ${table.className}DO selectBy${TreeParentJavaField}And${TreeNameJavaField}(Long ${treeParentColumn.javaField}, String ${treeNameColumn.javaField}) {
return selectOne(${table.className}DO::get${TreeParentJavaField}, ${treeParentColumn.javaField}, ${table.className}DO::get${TreeNameJavaField}, ${treeNameColumn.javaField});
}
default Long selectCountBy${TreeParentJavaField}(${treeParentColumn.javaType} ${treeParentColumn.javaField}) {
return selectCount(${table.className}DO::get${TreeParentJavaField}, ${treeParentColumn.javaField});
}
#end
} }

View File

@ -0,0 +1,51 @@
#set ($subTable = $subTables.get($subIndex))##当前表
#set ($subColumns = $subJoinColumnsList.get($subIndex))##当前字段数组
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
package ${basePackage}.module.${subTable.moduleName}.dal.mysql.${subTable.businessName};
import java.util.*;
import ${PageResultClassName};
import ${PageParamClassName};
import ${QueryWrapperClassName};
import ${BaseMapperClassName};
import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO;
import org.apache.ibatis.annotations.Mapper;
/**
* ${subTable.classComment} Mapper
*
* @author ${subTable.author}
*/
@Mapper
public interface ${subTable.className}Mapper extends BaseMapperX<${subTable.className}DO> {
## 情况一MASTER_ERP 时,需要分查询页子表
#if ( $table.templateType == 11 )
default PageResult<${subTable.className}DO> selectPage(PageParam reqVO, ${subJoinColumn.javaType} ${subJoinColumn.javaField}) {
return selectPage(reqVO, new LambdaQueryWrapperX<${subTable.className}DO>()
.eq(${subTable.className}DO::get${SubJoinColumnName}, ${subJoinColumn.javaField})
.orderByDesc(${subTable.className}DO::getId));## 大多数情况下id 倒序
}
## 情况二:非 MASTER_ERP 时,需要列表查询子表
#else
#if ( $subTable.subJoinMany)
default List<${subTable.className}DO> selectListBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}) {
return selectList(${subTable.className}DO::get${SubJoinColumnName}, ${subJoinColumn.javaField});
}
#else
default ${subTable.className}DO selectBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}) {
return selectOne(${subTable.className}DO::get${SubJoinColumnName}, ${subJoinColumn.javaField});
}
#end
#end
default int deleteBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}) {
return delete(${subTable.className}DO::get${SubJoinColumnName}, ${subJoinColumn.javaField});
}
}

View File

@ -1,3 +1,22 @@
// TODO 待办:请将下面的错误码复制到 yudao-module-${table.moduleName}-api 模块的 ErrorCodeConstants 类中。注意请给“TODO 补充编号”设置一个错误码编号!!! // TODO 待办:请将下面的错误码复制到 yudao-module-${table.moduleName}-api 模块的 ErrorCodeConstants 类中。注意请给“TODO 补充编号”设置一个错误码编号!!!
// ========== ${table.classComment} TODO 补充编号 ========== // ========== ${table.classComment} TODO 补充编号 ==========
ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS = new ErrorCode(TODO 补充编号, "${table.classComment}不存在"); ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS = new ErrorCode(TODO 补充编号, "${table.classComment}不存在");
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_EXITS_CHILDREN = new ErrorCode(TODO 补充编号, "存在存在子${table.classComment},无法删除");
ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_PARENT_NOT_EXITS = new ErrorCode(TODO 补充编号,"父级${table.classComment}不存在");
ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_PARENT_ERROR = new ErrorCode(TODO 补充编号, "不能设置自己为父${table.classComment}");
ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_${treeNameColumn_javaField_underlineCase.toUpperCase()}_DUPLICATE = new ErrorCode(TODO 补充编号, "已经存在该${treeNameColumn.columnComment}的${table.classComment}");
ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_PARENT_IS_CHILD = new ErrorCode(TODO 补充编号, "不能设置自己的子${table.className}为父${table.className}");
#end
## 特殊:主子表专属逻辑
#if ( $table.templateType == 11 )## 特殊ERP 情况
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($simpleClassNameUnderlineCase = $simpleClassNameUnderlineCases.get($index))
ErrorCode ${simpleClassNameUnderlineCase.toUpperCase()}_NOT_EXISTS = new ErrorCode(TODO 补充编号, "${subTable.classComment}不存在");
#if ( !$subTable.subJoinMany )
ErrorCode ${simpleClassNameUnderlineCase.toUpperCase()}_EXISTS = new ErrorCode(TODO 补充编号, "${subTable.classComment}已存在");
#end
#end
#end

View File

@ -4,7 +4,12 @@ import java.util.*;
import javax.validation.*; import javax.validation.*;
import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*;
import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO;
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO;
#end
import ${PageResultClassName}; import ${PageResultClassName};
import ${PageParamClassName};
/** /**
* ${table.classComment} Service 接口 * ${table.classComment} Service 接口
@ -19,14 +24,14 @@ public interface ${table.className}Service {
* @param createReqVO 创建信息 * @param createReqVO 创建信息
* @return 编号 * @return 编号
*/ */
${primaryColumn.javaType} create${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO); ${primaryColumn.javaType} create${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO);
/** /**
* 更新${table.classComment} * 更新${table.classComment}
* *
* @param updateReqVO 更新信息 * @param updateReqVO 更新信息
*/ */
void update${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO); void update${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO);
/** /**
* 删除${table.classComment} * 删除${table.classComment}
@ -43,14 +48,8 @@ public interface ${table.className}Service {
*/ */
${table.className}DO get${simpleClassName}(${primaryColumn.javaType} id); ${table.className}DO get${simpleClassName}(${primaryColumn.javaType} id);
/** ## 特殊:树表专属逻辑(树不需要分页接口)
* 获得${table.classComment}列表 #if ( $table.templateType != 2 )
*
* @param ids 编号
* @return ${table.classComment}列表
*/
List<${table.className}DO> get${simpleClassName}List(Collection<${primaryColumn.javaType}> ids);
/** /**
* 获得${table.classComment}分页 * 获得${table.classComment}分页
* *
@ -58,13 +57,91 @@ public interface ${table.className}Service {
* @return ${table.classComment}分页 * @return ${table.classComment}分页
*/ */
PageResult<${table.className}DO> get${simpleClassName}Page(${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO); PageResult<${table.className}DO> get${simpleClassName}Page(${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO);
#else
/** /**
* 获得${table.classComment}列表, 用于 Excel 导出 * 获得${table.classComment}列表
* *
* @param exportReqVO 查询条件 * @param listReqVO 查询条件
* @return ${table.classComment}列表 * @return ${table.classComment}列表
*/ */
List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ExportReqVO exportReqVO); List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO);
#end
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
#set ($subClassNameVar = $subClassNameVars.get($index))
// ==================== 子表($subTable.classComment ====================
## 情况一MASTER_ERP 时,需要分查询页子表
#if ( $table.templateType == 11 )
/**
* 获得${subTable.classComment}分页
*
* @param pageReqVO 分页查询
* @param ${subJoinColumn.javaField} ${subJoinColumn.columnComment}
* @return ${subTable.classComment}分页
*/
PageResult<${subTable.className}DO> get${subSimpleClassName}Page(PageParam pageReqVO, ${subJoinColumn.javaType} ${subJoinColumn.javaField});
## 情况二:非 MASTER_ERP 时,需要列表查询子表
#else
#if ( $subTable.subJoinMany )
/**
* 获得${subTable.classComment}列表
*
* @param ${subJoinColumn.javaField} ${subJoinColumn.columnComment}
* @return ${subTable.classComment}列表
*/
List<${subTable.className}DO> get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField});
#else
/**
* 获得${subTable.classComment}
*
* @param ${subJoinColumn.javaField} ${subJoinColumn.columnComment}
* @return ${subTable.classComment}
*/
${subTable.className}DO get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField});
#end
#end
## 特殊MASTER_ERP 时,支持单个的新增、修改、删除操作
#if ( $table.templateType == 11 )
/**
* 创建${subTable.classComment}
*
* @param ${subClassNameVar} 创建信息
* @return 编号
*/
${subPrimaryColumn.javaType} create${subSimpleClassName}(@Valid ${subTable.className}DO ${subClassNameVar});
/**
* 更新${subTable.classComment}
*
* @param ${subClassNameVar} 更新信息
*/
void update${subSimpleClassName}(@Valid ${subTable.className}DO ${subClassNameVar});
/**
* 删除${subTable.classComment}
*
* @param id 编号
*/
void delete${subSimpleClassName}(${subPrimaryColumn.javaType} id);
/**
* 获得${subTable.classComment}
*
* @param id 编号
* @return ${subTable.classComment}
*/
${subTable.className}DO get${subSimpleClassName}(${subPrimaryColumn.javaType} id);
#end
#end
} }

View File

@ -3,21 +3,29 @@ package ${basePackage}.module.${table.moduleName}.service.${table.businessName};
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*; import java.util.*;
import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*;
import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO;
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO;
#end
import ${PageResultClassName}; import ${PageResultClassName};
import ${PageParamClassName};
import ${BeanUtils};
import ${basePackage}.module.${table.moduleName}.convert.${table.businessName}.${table.className}Convert;
import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper; import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper;
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
import ${basePackage}.module.${subTable.moduleName}.dal.mysql.${subTable.businessName}.${subTable.className}Mapper;
#end
import static ${ServiceExceptionUtilClassName}.exception; import static ${ServiceExceptionUtilClassName}.exception;
import static ${basePackage}.module.${table.moduleName}.enums.ErrorCodeConstants.*; import static ${basePackage}.module.${table.moduleName}.enums.ErrorCodeConstants.*;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
/** /**
* ${table.classComment} Service 实现类 * ${table.classComment} Service 实现类
* *
@ -29,31 +37,121 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
@Resource @Resource
private ${table.className}Mapper ${classNameVar}Mapper; private ${table.className}Mapper ${classNameVar}Mapper;
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
@Resource
private ${subTable.className}Mapper ${subClassNameVars.get($index)}Mapper;
#end
@Override @Override
public ${primaryColumn.javaType} create${simpleClassName}(${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO) { ## 特殊:主子表专属逻辑(非 ERP 模式)
#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
@Transactional(rollbackFor = Exception.class)
#end
public ${primaryColumn.javaType} create${simpleClassName}(${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO) {
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写
#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写
// 校验${treeParentColumn.columnComment}的有效性
validateParent${simpleClassName}(null, createReqVO.get${TreeParentJavaField}());
// 校验${treeNameColumn.columnComment}的唯一性
validate${simpleClassName}${TreeNameJavaField}Unique(null, createReqVO.get${TreeParentJavaField}(), createReqVO.get${TreeNameJavaField}());
#end
// 插入 // 插入
${table.className}DO ${classNameVar} = ${table.className}Convert.INSTANCE.convert(createReqVO); ${table.className}DO ${classNameVar} = BeanUtils.toBean(createReqVO, ${table.className}DO.class);
${classNameVar}Mapper.insert(${classNameVar}); ${classNameVar}Mapper.insert(${classNameVar});
## 特殊:主子表专属逻辑(非 ERP 模式)
#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
// 插入子表
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
#if ( $subTable.subJoinMany)
create${subSimpleClassName}List(${classNameVar}.getId(), createReqVO.get${subSimpleClassNames.get($index)}s());
#else
create${subSimpleClassName}(${classNameVar}.getId(), createReqVO.get${subSimpleClassNames.get($index)}());
#end
#end
#end
// 返回 // 返回
return ${classNameVar}.getId(); return ${classNameVar}.getId();
} }
@Override @Override
public void update${simpleClassName}(${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO) { ## 特殊:主子表专属逻辑(非 ERP 模式)
#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
@Transactional(rollbackFor = Exception.class)
#end
public void update${simpleClassName}(${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO) {
// 校验存在 // 校验存在
validate${simpleClassName}Exists(updateReqVO.getId()); validate${simpleClassName}Exists(updateReqVO.getId());
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写
#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写
// 校验${treeParentColumn.columnComment}的有效性
validateParent${simpleClassName}(updateReqVO.getId(), updateReqVO.get${TreeParentJavaField}());
// 校验${treeNameColumn.columnComment}的唯一性
validate${simpleClassName}${TreeNameJavaField}Unique(updateReqVO.getId(), updateReqVO.get${TreeParentJavaField}(), updateReqVO.get${TreeNameJavaField}());
#end
// 更新 // 更新
${table.className}DO updateObj = ${table.className}Convert.INSTANCE.convert(updateReqVO); ${table.className}DO updateObj = BeanUtils.toBean(updateReqVO, ${table.className}DO.class);
${classNameVar}Mapper.updateById(updateObj); ${classNameVar}Mapper.updateById(updateObj);
## 特殊:主子表专属逻辑(非 ERP 模式)
#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11)
// 更新子表
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
#if ( $subTable.subJoinMany)
update${subSimpleClassName}List(updateReqVO.getId(), updateReqVO.get${subSimpleClassNames.get($index)}s());
#else
update${subSimpleClassName}(updateReqVO.getId(), updateReqVO.get${subSimpleClassNames.get($index)}());
#end
#end
#end
} }
@Override @Override
## 特殊:主子表专属逻辑
#if ( $subTables && $subTables.size() > 0)
@Transactional(rollbackFor = Exception.class)
#end
public void delete${simpleClassName}(${primaryColumn.javaType} id) { public void delete${simpleClassName}(${primaryColumn.javaType} id) {
// 校验存在 // 校验存在
validate${simpleClassName}Exists(id); validate${simpleClassName}Exists(id);
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
#set ($ParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写
// 校验是否有子${table.classComment}
if (${classNameVar}Mapper.selectCountBy${ParentJavaField}(id) > 0) {
throw exception(${simpleClassName_underlineCase.toUpperCase()}_EXITS_CHILDREN);
}
#end
// 删除 // 删除
${classNameVar}Mapper.deleteById(id); ${classNameVar}Mapper.deleteById(id);
## 特殊:主子表专属逻辑
#if ( $subTables && $subTables.size() > 0)
// 删除子表
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
delete${subSimpleClassName}By${SubJoinColumnName}(id);
#end
#end
} }
private void validate${simpleClassName}Exists(${primaryColumn.javaType} id) { private void validate${simpleClassName}Exists(${primaryColumn.javaType} id) {
@ -62,27 +160,191 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
} }
} }
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写
#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写
private void validateParent${simpleClassName}(Long id, Long ${treeParentColumn.javaField}) {
if (${treeParentColumn.javaField} == null || ${simpleClassName}DO.${treeParentColumn_javaField_underlineCase.toUpperCase()}_ROOT.equals(${treeParentColumn.javaField})) {
return;
}
// 1. 不能设置自己为父${table.classComment}
if (Objects.equals(id, ${treeParentColumn.javaField})) {
throw exception(${simpleClassName_underlineCase.toUpperCase()}_PARENT_ERROR);
}
// 2. 父${table.classComment}不存在
${simpleClassName}DO parent${simpleClassName} = ${classNameVar}Mapper.selectById(${treeParentColumn.javaField});
if (parent${simpleClassName} == null) {
throw exception(${simpleClassName_underlineCase.toUpperCase()}_PARENT_NOT_EXITS);
}
// 3. 递归校验父${table.classComment},如果父${table.classComment}是自己的子${table.classComment},则报错,避免形成环路
if (id == null) { // id 为空,说明新增,不需要考虑环路
return;
}
for (int i = 0; i < Short.MAX_VALUE; i++) {
// 3.1 校验环路
${treeParentColumn.javaField} = parent${simpleClassName}.get${TreeParentJavaField}();
if (Objects.equals(id, ${treeParentColumn.javaField})) {
throw exception(${simpleClassName_underlineCase.toUpperCase()}_PARENT_IS_CHILD);
}
// 3.2 继续递归下一级父${table.classComment}
if (${treeParentColumn.javaField} == null || ${simpleClassName}DO.${treeParentColumn_javaField_underlineCase.toUpperCase()}_ROOT.equals(${treeParentColumn.javaField})) {
break;
}
parent${simpleClassName} = ${classNameVar}Mapper.selectById(${treeParentColumn.javaField});
if (parent${simpleClassName} == null) {
break;
}
}
}
private void validate${simpleClassName}${TreeNameJavaField}Unique(Long id, Long ${treeParentColumn.javaField}, String ${treeNameColumn.javaField}) {
${simpleClassName}DO ${classNameVar} = ${classNameVar}Mapper.selectBy${TreeParentJavaField}And${TreeNameJavaField}(${treeParentColumn.javaField}, ${treeNameColumn.javaField});
if (${classNameVar} == null) {
return;
}
// 如果 id 为空,说明不用比较是否为相同 id 的${table.classComment}
if (id == null) {
throw exception(${simpleClassName_underlineCase.toUpperCase()}_${treeNameColumn_javaField_underlineCase.toUpperCase()}_DUPLICATE);
}
if (!Objects.equals(${classNameVar}.getId(), id)) {
throw exception(${simpleClassName_underlineCase.toUpperCase()}_${treeNameColumn_javaField_underlineCase.toUpperCase()}_DUPLICATE);
}
}
#end
@Override @Override
public ${table.className}DO get${simpleClassName}(${primaryColumn.javaType} id) { public ${table.className}DO get${simpleClassName}(${primaryColumn.javaType} id) {
return ${classNameVar}Mapper.selectById(id); return ${classNameVar}Mapper.selectById(id);
} }
@Override ## 特殊:树表专属逻辑(树不需要分页接口)
public List<${table.className}DO> get${simpleClassName}List(Collection<${primaryColumn.javaType}> ids) { #if ( $table.templateType != 2 )
if (CollUtil.isEmpty(ids)) {
return ListUtil.empty();
}
return ${classNameVar}Mapper.selectBatchIds(ids);
}
@Override @Override
public PageResult<${table.className}DO> get${simpleClassName}Page(${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO) { public PageResult<${table.className}DO> get${simpleClassName}Page(${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO) {
return ${classNameVar}Mapper.selectPage(pageReqVO); return ${classNameVar}Mapper.selectPage(pageReqVO);
} }
#else
@Override
public List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO) {
return ${classNameVar}Mapper.selectList(listReqVO);
}
#end
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($simpleClassNameUnderlineCase = $simpleClassNameUnderlineCases.get($index))
#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
#set ($subClassNameVar = $subClassNameVars.get($index))
// ==================== 子表($subTable.classComment ====================
## 情况一MASTER_ERP 时,需要分查询页子表
#if ( $table.templateType == 11 )
@Override
public PageResult<${subTable.className}DO> get${subSimpleClassName}Page(PageParam pageReqVO, ${subJoinColumn.javaType} ${subJoinColumn.javaField}) {
return ${subClassNameVars.get($index)}Mapper.selectPage(pageReqVO, ${subJoinColumn.javaField});
}
## 情况二:非 MASTER_ERP 时,需要列表查询子表
#else
#if ( $subTable.subJoinMany )
@Override
public List<${subTable.className}DO> get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}) {
return ${subClassNameVars.get($index)}Mapper.selectListBy${SubJoinColumnName}(${subJoinColumn.javaField});
}
#else
@Override
public ${subTable.className}DO get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}) {
return ${subClassNameVars.get($index)}Mapper.selectBy${SubJoinColumnName}(${subJoinColumn.javaField});
}
#end
#end
## 情况一MASTER_ERP 时,支持单个的新增、修改、删除操作
#if ( $table.templateType == 11 )
@Override
public ${subPrimaryColumn.javaType} create${subSimpleClassName}(${subTable.className}DO ${subClassNameVar}) {
## 特殊:一对一时,需要保证只有一条,不能重复插入
#if ( !$subTable.subJoinMany)
// 校验是否已经存在
if (${subClassNameVars.get($index)}Mapper.selectBy${SubJoinColumnName}(${subClassNameVar}.get${SubJoinColumnName}()) != null) {
throw exception(${simpleClassNameUnderlineCase.toUpperCase()}_EXISTS);
}
// 插入
#end
${subClassNameVars.get($index)}Mapper.insert(${subClassNameVar});
return ${subClassNameVar}.getId();
}
@Override @Override
public List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ExportReqVO exportReqVO) { public void update${subSimpleClassName}(${subTable.className}DO ${subClassNameVar}) {
return ${classNameVar}Mapper.selectList(exportReqVO); // 校验存在
validate${subSimpleClassName}Exists(${subClassNameVar}.getId());
// 更新
${subClassNameVars.get($index)}Mapper.updateById(${subClassNameVar});
} }
@Override
public void delete${subSimpleClassName}(${subPrimaryColumn.javaType} id) {
// 校验存在
validate${subSimpleClassName}Exists(id);
// 删除
${subClassNameVars.get($index)}Mapper.deleteById(id);
}
@Override
public ${subTable.className}DO get${subSimpleClassName}(${subPrimaryColumn.javaType} id) {
return ${subClassNameVars.get($index)}Mapper.selectById(id);
}
private void validate${subSimpleClassName}Exists(${subPrimaryColumn.javaType} id) {
if (${subClassNameVar}Mapper.selectById(id) == null) {
throw exception(${simpleClassNameUnderlineCase.toUpperCase()}_NOT_EXISTS);
}
}
## 情况二:非 MASTER_ERP 时,支持批量的新增、修改操作
#else
#if ( $subTable.subJoinMany)
private void create${subSimpleClassName}List(${primaryColumn.javaType} ${subJoinColumn.javaField}, List<${subTable.className}DO> list) {
list.forEach(o -> o.set$SubJoinColumnName(${subJoinColumn.javaField}));
${subClassNameVars.get($index)}Mapper.insertBatch(list);
}
private void update${subSimpleClassName}List(${primaryColumn.javaType} ${subJoinColumn.javaField}, List<${subTable.className}DO> list) {
delete${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField});
list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下1id 冲突2updateTime 不更新
create${subSimpleClassName}List(${subJoinColumn.javaField}, list);
}
#else
private void create${subSimpleClassName}(${primaryColumn.javaType} ${subJoinColumn.javaField}, ${subTable.className}DO ${subClassNameVar}) {
if (${subClassNameVar} == null) {
return;
}
${subClassNameVar}.set$SubJoinColumnName(${subJoinColumn.javaField});
${subClassNameVars.get($index)}Mapper.insert(${subClassNameVar});
}
private void update${subSimpleClassName}(${primaryColumn.javaType} ${subJoinColumn.javaField}, ${subTable.className}DO ${subClassNameVar}) {
if (${subClassNameVar} == null) {
return;
}
${subClassNameVar}.set$SubJoinColumnName(${subJoinColumn.javaField});
${subClassNameVar}.setUpdater(null).setUpdateTime(null); // 解决更新情况下updateTime 不更新
${subClassNameVars.get($index)}Mapper.insertOrUpdate(${subClassNameVar});
}
#end
#end
private void delete${subSimpleClassName}By${SubJoinColumnName}(${primaryColumn.javaType} ${subJoinColumn.javaField}) {
${subClassNameVars.get($index)}Mapper.deleteBy${SubJoinColumnName}(${subJoinColumn.javaField});
}
#end
} }

View File

@ -77,15 +77,15 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest {
@Test @Test
public void testCreate${simpleClassName}_success() { public void testCreate${simpleClassName}_success() {
// 准备参数 // 准备参数
${sceneEnum.prefixClass}${table.className}CreateReqVO reqVO = randomPojo(${sceneEnum.prefixClass}${table.className}CreateReqVO.class); ${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO = randomPojo(${sceneEnum.prefixClass}${table.className}SaveReqVO.class).setId(null);
// 调用 // 调用
${primaryColumn.javaType} ${classNameVar}Id = ${classNameVar}Service.create${simpleClassName}(reqVO); ${primaryColumn.javaType} ${classNameVar}Id = ${classNameVar}Service.create${simpleClassName}(createReqVO);
// 断言 // 断言
assertNotNull(${classNameVar}Id); assertNotNull(${classNameVar}Id);
// 校验记录的属性是否正确 // 校验记录的属性是否正确
${table.className}DO ${classNameVar} = ${classNameVar}Mapper.selectById(${classNameVar}Id); ${table.className}DO ${classNameVar} = ${classNameVar}Mapper.selectById(${classNameVar}Id);
assertPojoEquals(reqVO, ${classNameVar}); assertPojoEquals(createReqVO, ${classNameVar}, "id");
} }
@Test @Test
@ -94,24 +94,24 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest {
${table.className}DO db${simpleClassName} = randomPojo(${table.className}DO.class); ${table.className}DO db${simpleClassName} = randomPojo(${table.className}DO.class);
${classNameVar}Mapper.insert(db${simpleClassName});// @Sql: 先插入出一条存在的数据 ${classNameVar}Mapper.insert(db${simpleClassName});// @Sql: 先插入出一条存在的数据
// 准备参数 // 准备参数
${sceneEnum.prefixClass}${table.className}UpdateReqVO reqVO = randomPojo(${sceneEnum.prefixClass}${table.className}UpdateReqVO.class, o -> { ${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO = randomPojo(${sceneEnum.prefixClass}${table.className}SaveReqVO.class, o -> {
o.setId(db${simpleClassName}.getId()); // 设置更新的 ID o.setId(db${simpleClassName}.getId()); // 设置更新的 ID
}); });
// 调用 // 调用
${classNameVar}Service.update${simpleClassName}(reqVO); ${classNameVar}Service.update${simpleClassName}(updateReqVO);
// 校验是否更新正确 // 校验是否更新正确
${table.className}DO ${classNameVar} = ${classNameVar}Mapper.selectById(reqVO.getId()); // 获取最新的 ${table.className}DO ${classNameVar} = ${classNameVar}Mapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, ${classNameVar}); assertPojoEquals(updateReqVO, ${classNameVar});
} }
@Test @Test
public void testUpdate${simpleClassName}_notExists() { public void testUpdate${simpleClassName}_notExists() {
// 准备参数 // 准备参数
${sceneEnum.prefixClass}${table.className}UpdateReqVO reqVO = randomPojo(${sceneEnum.prefixClass}${table.className}UpdateReqVO.class); ${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO = randomPojo(${sceneEnum.prefixClass}${table.className}SaveReqVO.class);
// 调用, 并断言异常 // 调用, 并断言异常
assertServiceException(() -> ${classNameVar}Service.update${simpleClassName}(reqVO), ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS); assertServiceException(() -> ${classNameVar}Service.update${simpleClassName}(updateReqVO), ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS);
} }
@Test @Test
@ -137,6 +137,8 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest {
assertServiceException(() -> ${classNameVar}Service.delete${simpleClassName}(id), ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS); assertServiceException(() -> ${classNameVar}Service.delete${simpleClassName}(id), ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS);
} }
## 特殊:树表专属逻辑(树不需要分页接口)
#if ( $table.templateType != 2 )
@Test @Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGet${simpleClassName}Page() { public void testGet${simpleClassName}Page() {
@ -149,11 +151,11 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest {
assertEquals(1, pageResult.getList().size()); assertEquals(1, pageResult.getList().size());
assertPojoEquals(db${simpleClassName}, pageResult.getList().get(0)); assertPojoEquals(db${simpleClassName}, pageResult.getList().get(0));
} }
#else
@Test @Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGet${simpleClassName}List() { public void testGet${simpleClassName}List() {
#getPageCondition("ExportReqVO") #getPageCondition("ListReqVO")
// 调用 // 调用
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(reqVO); List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(reqVO);
@ -161,5 +163,6 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest {
assertEquals(1, list.size()); assertEquals(1, list.size());
assertPojoEquals(db${simpleClassName}, list.get(0)); assertPojoEquals(db${simpleClassName}, list.get(0));
} }
#end
} }

View File

@ -23,6 +23,8 @@ CREATE TABLE IF NOT EXISTS "${table.tableName.toLowerCase()}" (
"${column.columnName}" ${dataType} DEFAULT '', "${column.columnName}" ${dataType} DEFAULT '',
#elseif (${column.columnName} == 'deleted') #elseif (${column.columnName} == 'deleted')
"deleted" bit NOT NULL DEFAULT FALSE, "deleted" bit NOT NULL DEFAULT FALSE,
#elseif (${column.columnName} == 'tenantId')
"tenant_id" bigint NOT NULL DEFAULT 0,
#else #else
"${column.columnName.toLowerCase()}" ${dataType}#if (${column.nullable} == false) NOT NULL#end, "${column.columnName.toLowerCase()}" ${dataType}#if (${column.nullable} == false) NOT NULL#end,
#end #end

View File

@ -5,7 +5,7 @@ INSERT INTO system_menu(
) )
VALUES ( VALUES (
'${table.classComment}管理', '', 2, 0, ${table.parentMenuId}, '${table.classComment}管理', '', 2, 0, ${table.parentMenuId},
'${simpleClassName_strikeCase}', '', '${table.moduleName}/${classNameVar}/index', 0, '${table.className}' '${simpleClassName_strikeCase}', '', '${table.moduleName}/${table.businessName}/index', 0, '${table.className}'
); );
-- 按钮父菜单ID -- 按钮父菜单ID

View File

@ -15,10 +15,17 @@ export interface ${simpleClassName}VO {
#end #end
} }
// 查询${table.classComment}列表 #if ( $table.templateType != 2 )
// 查询${table.classComment}分页
export const get${simpleClassName}Page = async (params) => { export const get${simpleClassName}Page = async (params) => {
return await request.get({ url: `${baseURL}/page`, params }) return await request.get({ url: `${baseURL}/page`, params })
} }
#else
// 查询${table.classComment}列表
export const get${simpleClassName}List = async (params) => {
return await request.get({ url: `${baseURL}/list`, params })
}
#end
// 查询${table.classComment}详情 // 查询${table.classComment}详情
export const get${simpleClassName} = async (id: number) => { export const get${simpleClassName} = async (id: number) => {
@ -44,3 +51,61 @@ export const delete${simpleClassName} = async (id: number) => {
export const export${simpleClassName} = async (params) => { export const export${simpleClassName} = async (params) => {
return await request.download({ url: `${baseURL}/export-excel`, params }) return await request.download({ url: `${baseURL}/export-excel`, params })
} }
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
#set ($subClassNameVar = $subClassNameVars.get($index))
// ==================== 子表($subTable.classComment ====================
## 情况一MASTER_ERP 时,需要分查询页子表
#if ( $table.templateType == 11 )
// 获得${subTable.classComment}分页
export const get${subSimpleClassName}Page = async (params) => {
return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/page`, params })
}
## 情况二:非 MASTER_ERP 时,需要列表查询子表
#else
#if ( $subTable.subJoinMany )
// 获得${subTable.classComment}列表
export const get${subSimpleClassName}ListBy${SubJoinColumnName} = async (${subJoinColumn.javaField}) => {
return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField} })
}
#else
// 获得${subTable.classComment}
export const get${subSimpleClassName}By${SubJoinColumnName} = async (${subJoinColumn.javaField}) => {
return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField} })
}
#end
#end
## 特殊MASTER_ERP 时,支持单个的新增、修改、删除操作
#if ( $table.templateType == 11 )
// 新增${subTable.classComment}
export const create${subSimpleClassName} = async (data) => {
return await request.post({ url: `${baseURL}/${subSimpleClassName_strikeCase}/create`, data })
}
// 修改${subTable.classComment}
export const update${subSimpleClassName} = async (data) => {
return await request.put({ url: `${baseURL}/${subSimpleClassName_strikeCase}/update`, data })
}
// 删除${subTable.classComment}
export const delete${subSimpleClassName} = async (id: number) => {
return await request.delete({ url: `${baseURL}/${subSimpleClassName_strikeCase}/delete?id=` + id })
}
// 获得${subTable.classComment}
export const get${subSimpleClassName} = async (id: number) => {
return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/get?id=` + id })
}
#end
#end

View File

@ -0,0 +1,205 @@
#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
#foreach($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "getIntDictOptions")
#elseif ($javaType == "String")
#set ($dictMethod = "getStrDictOptions")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "getBoolDictOptions")
#end
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")## 图片上传
<el-form-item label="${comment}" prop="${javaField}">
<UploadImg v-model="formData.${javaField}" />
</el-form-item>
#elseif($column.htmlType == "fileUpload")## 文件上传
<el-form-item label="${comment}" prop="${javaField}">
<UploadFile v-model="formData.${javaField}" />
</el-form-item>
#elseif($column.htmlType == "editor")## 文本编辑器
<el-form-item label="${comment}" prop="${javaField}">
<Editor v-model="formData.${javaField}" height="150px" />
</el-form-item>
#elseif($column.htmlType == "select")## 下拉框
<el-form-item label="${comment}" prop="${javaField}">
<el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
#if ("" != $dictType)## 有数据字典
<el-option
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else##没数据字典
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox")## 多选框
<el-form-item label="${comment}" prop="${javaField}">
<el-checkbox-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-checkbox
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-checkbox>
#else##没数据字典
<el-checkbox>请选择字典生成</el-checkbox>
#end
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio")## 单选框
<el-form-item label="${comment}" prop="${javaField}">
<el-radio-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-radio
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
#else##没数据字典
<el-radio label="1">请选择字典生成</el-radio>
#end
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "datetime")## 时间框
<el-form-item label="${comment}" prop="${javaField}">
<el-date-picker
v-model="formData.${javaField}"
type="date"
value-format="x"
placeholder="选择${comment}"
/>
</el-form-item>
#elseif($column.htmlType == "textarea")## 文本框
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" />
</el-form-item>
#end
#end
#end
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
})
const formRules = reactive({
#foreach ($column in $subColumns)
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
#set($comment=$column.columnComment)
$column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
#end
#end
})
const formRef = ref() // 表单 Ref
/** 打开弹窗 */
const open = async (type: string, id?: number, ${subJoinColumn.javaField}: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.${subJoinColumn.javaField} = ${subJoinColumn.javaField}
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await ${simpleClassName}Api.get${subSimpleClassName}(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
const data = formData.value
if (formType.value === 'create') {
await ${simpleClassName}Api.create${subSimpleClassName}(data)
message.success(t('common.createSuccess'))
} else {
await ${simpleClassName}Api.update${subSimpleClassName}(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,2 @@
## 主表的 normal 和 inner 使用相同的 form 表单
#parse("codegen/vue3/views/components/form_sub_normal.vue.vm")

View File

@ -0,0 +1,362 @@
#set ($subTable = $subTables.get($subIndex))##当前表
#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
<template>
#if ( $subTable.subJoinMany )## 情况一一对多table + form
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
>
<el-table :data="formData" class="-mt-10px">
<el-table-column label="序号" type="index" width="100" />
#foreach($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "getIntDictOptions")
#elseif ($javaType == "String")
#set ($dictMethod = "getStrDictOptions")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "getBoolDictOptions")
#end
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
<el-table-column label="${comment}" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-input v-model="row.${javaField}" placeholder="请输入${comment}" />
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "imageUpload")## 图片上传
<el-table-column label="${comment}" min-width="200">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<UploadImg v-model="row.${javaField}" />
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "fileUpload")## 文件上传
<el-table-column label="${comment}" min-width="200">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<UploadFile v-model="row.${javaField}" />
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "editor")## 文本编辑器
<el-table-column label="${comment}" min-width="400">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<Editor v-model="row.${javaField}" height="150px" />
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "select")## 下拉框
<el-table-column label="${comment}" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-select v-model="row.${javaField}" placeholder="请选择${comment}">
#if ("" != $dictType)## 有数据字典
<el-option
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else##没数据字典
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "checkbox")## 多选框
<el-table-column label="${comment}" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-checkbox-group v-model="row.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-checkbox
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-checkbox>
#else##没数据字典
<el-checkbox>请选择字典生成</el-checkbox>
#end
</el-checkbox-group>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "radio")## 单选框
<el-table-column label="${comment}" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-radio-group v-model="row.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-radio
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
#else##没数据字典
<el-radio label="1">请选择字典生成</el-radio>
#end
</el-radio-group>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "datetime")## 时间框
<el-table-column label="${comment}" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-date-picker
v-model="row.${javaField}"
type="date"
value-format="x"
placeholder="选择${comment}"
/>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "textarea")## 文本框
<el-table-column label="${comment}" min-width="200">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-input v-model="row.${javaField}" type="textarea" placeholder="请输入${comment}" />
</el-form-item>
</template>
</el-table-column>
#end
#end
#end
<el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button @click="handleDelete($index)" link>—</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3">
<el-button @click="handleAdd" round>+ 添加${subTable.classComment}</el-button>
</el-row>
#else## 情况二一对一form
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
#foreach($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "getIntDictOptions")
#elseif ($javaType == "String")
#set ($dictMethod = "getStrDictOptions")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "getBoolDictOptions")
#end
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")## 图片上传
<el-form-item label="${comment}" prop="${javaField}">
<UploadImg v-model="formData.${javaField}" />
</el-form-item>
#elseif($column.htmlType == "fileUpload")## 文件上传
<el-form-item label="${comment}" prop="${javaField}">
<UploadFile v-model="formData.${javaField}" />
</el-form-item>
#elseif($column.htmlType == "editor")## 文本编辑器
<el-form-item label="${comment}" prop="${javaField}">
<Editor v-model="formData.${javaField}" height="150px" />
</el-form-item>
#elseif($column.htmlType == "select")## 下拉框
<el-form-item label="${comment}" prop="${javaField}">
<el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
#if ("" != $dictType)## 有数据字典
<el-option
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else##没数据字典
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox")## 多选框
<el-form-item label="${comment}" prop="${javaField}">
<el-checkbox-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-checkbox
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-checkbox>
#else##没数据字典
<el-checkbox>请选择字典生成</el-checkbox>
#end
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio")## 单选框
<el-form-item label="${comment}" prop="${javaField}">
<el-radio-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-radio
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
#else##没数据字典
<el-radio label="1">请选择字典生成</el-radio>
#end
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "datetime")## 时间框
<el-form-item label="${comment}" prop="${javaField}">
<el-date-picker
v-model="formData.${javaField}"
type="date"
value-format="x"
placeholder="选择${comment}"
/>
</el-form-item>
#elseif($column.htmlType == "textarea")## 文本框
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" />
</el-form-item>
#end
#end
#end
</el-form>
#end
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
const props = defineProps<{
${subJoinColumn.javaField}: undefined // ${subJoinColumn.columnComment}(主表的关联字段)
}>()
const formLoading = ref(false) // 表单的加载中
const formData = ref([])
const formRules = reactive({
#foreach ($column in $subColumns)
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
#set($comment=$column.columnComment)
$column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
#end
#end
})
const formRef = ref() // 表单 Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.${subJoinColumn.javaField},
async (val) => {
// 1. 重置表单
#if ( $subTable.subJoinMany )
formData.value = []
#else
formData.value = {
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
}
#end
// 2. val 非空,则加载数据
if (!val) {
return;
}
try {
formLoading.value = true
#if ( $subTable.subJoinMany )
formData.value = await ${simpleClassName}Api.get${subSimpleClassName}ListBy${SubJoinColumnName}(val)
#else
const data = await ${simpleClassName}Api.get${subSimpleClassName}By${SubJoinColumnName}(val)
if (!data) {
return
}
formData.value = data
#end
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
#if ( $subTable.subJoinMany )
/** 新增按钮操作 */
const handleAdd = () => {
const row = {
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
}
row.${subJoinColumn.javaField} = props.${subJoinColumn.javaField}
formData.value.push(row)
}
/** 删除按钮操作 */
const handleDelete = (index) => {
formData.value.splice(index, 1)
}
#end
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>

View File

@ -0,0 +1,181 @@
#set ($subTable = $subTables.get($subIndex))##当前表
#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
<template>
<!-- 列表 -->
<ContentWrap>
#if ($table.templateType == 11)
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['${permissionPrefix}:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
#end
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
#foreach($column in $subColumns)
#if ($column.listOperationResult)
#set ($dictType=$column.dictType)
#set ($javaField = $column.javaField)
#set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment=$column.columnComment)
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.javaType == "LocalDateTime")## 时间类型
<el-table-column
label="${comment}"
align="center"
prop="${javaField}"
:formatter="dateFormatter"
width="180px"
/>
#elseif($column.dictType && "" != $column.dictType)## 数据字典
<el-table-column label="${comment}" align="center" prop="${javaField}">
<template #default="scope">
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.${column.javaField}" />
</template>
</el-table-column>
#else
<el-table-column label="${comment}" align="center" prop="${javaField}" />
#end
#end
#end
#if ($table.templateType == 11)
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['${permissionPrefix}:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['${permissionPrefix}:delete']"
>
删除
</el-button>
</template>
</el-table-column>
#end
</el-table>
#if ($table.templateType == 11)
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
#end
</ContentWrap>
#if ($table.templateType == 11)
<!-- 表单弹窗:添加/修改 -->
<${subSimpleClassName}Form ref="formRef" @success="getList" />
#end
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
#if ($table.templateType == 11)
import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue'
#end
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const props = defineProps<{
${subJoinColumn.javaField}: undefined // ${subJoinColumn.columnComment}(主表的关联字段)
}>()
const loading = ref(false) // 列表的加载中
const list = ref([]) // 列表的数据
#if ($table.templateType == 11)
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
${subJoinColumn.javaField}: undefined
})
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.${subJoinColumn.javaField},
(val) => {
queryParams.${subJoinColumn.javaField} = val
handleQuery()
},
{ immediate: false }
)
#end
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
#if ($table.templateType == 11)
const data = await ${simpleClassName}Api.get${subSimpleClassName}Page(queryParams)
list.value = data.list
total.value = data.total
#else
#if ( $subTable.subJoinMany )
list.value = await ${simpleClassName}Api.get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField})
#else
const data = await ${simpleClassName}Api.get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField})
if (!data) {
return
}
list.value.push(data)
#end
#end
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
#if ($table.templateType == 11)
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
if (!props.${subJoinColumn.javaField}) {
message.error('请选择一个${table.classComment}')
return
}
formRef.value.open(type, id, props.${subJoinColumn.javaField})
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await ${simpleClassName}Api.delete${subSimpleClassName}(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
#end
#if ($table.templateType != 11)
/** 初始化 **/
onMounted(() => {
getList()
})
#end
</script>

View File

@ -0,0 +1,4 @@
## 子表的 erp 和 inner 使用相似的 list 列表,差异主要两点:
## 1inner 使用 list 不分页erp 使用 page 分页
## 2erp 支持单个子表的新增、修改、删除inner 不支持
#parse("codegen/vue3/views/components/list_sub_erp.vue.vm")

View File

@ -7,7 +7,6 @@
label-width="100px" label-width="100px"
v-loading="formLoading" v-loading="formLoading"
> >
#set ($dictMethods = [])## 使用到的 dict 字典方法
#foreach($column in $columns) #foreach($column in $columns)
#if ($column.createOperation || $column.updateOperation) #if ($column.createOperation || $column.updateOperation)
#set ($dictType = $column.dictType) #set ($dictType = $column.dictType)
@ -23,31 +22,41 @@
#elseif ($javaType == "Boolean") #elseif ($javaType == "Boolean")
#set ($dictMethod = "getBoolDictOptions") #set ($dictMethod = "getBoolDictOptions")
#end #end
#if ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 #if ( $table.templateType == 2 && $column.id == $treeParentColumn.id )
<el-form-item label="${comment}" prop="${javaField}">
<el-tree-select
v-model="formData.${javaField}"
:data="${classNameVar}Tree"
#if ($treeNameColumn.javaField == "name")
:props="defaultProps"
#else
:props="{...defaultProps, label: '$treeNameColumn.javaField'}"
#end
check-strictly
default-expand-all
placeholder="请选择${comment}"
/>
</el-form-item>
#elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
<el-form-item label="${comment}" prop="${javaField}"> <el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" placeholder="请输入${comment}" /> <el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
</el-form-item> </el-form-item>
#elseif($column.htmlType == "imageUpload")## 图片上传 #elseif($column.htmlType == "imageUpload")## 图片上传
#set ($hasImageUploadColumn = true) <el-form-item label="${comment}" prop="${javaField}">
<el-form-item label="${comment}">
<UploadImg v-model="formData.${javaField}" /> <UploadImg v-model="formData.${javaField}" />
</el-form-item> </el-form-item>
#elseif($column.htmlType == "fileUpload")## 文件上传 #elseif($column.htmlType == "fileUpload")## 文件上传
#set ($hasFileUploadColumn = true) <el-form-item label="${comment}" prop="${javaField}">
<el-form-item label="${comment}">
<UploadFile v-model="formData.${javaField}" /> <UploadFile v-model="formData.${javaField}" />
</el-form-item> </el-form-item>
#elseif($column.htmlType == "editor")## 文本编辑器 #elseif($column.htmlType == "editor")## 文本编辑器
<el-form-item label="${comment}"> <el-form-item label="${comment}" prop="${javaField}">
<Editor v-model="formData.${javaField}" height="150px" /> <Editor v-model="formData.${javaField}" height="150px" />
</el-form-item> </el-form-item>
#elseif($column.htmlType == "select")## 下拉框 #elseif($column.htmlType == "select")## 下拉框
<el-form-item label="${comment}" prop="${javaField}"> <el-form-item label="${comment}" prop="${javaField}">
<el-select v-model="formData.${javaField}" placeholder="请选择${comment}"> <el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
#if ("" != $dictType)## 有数据字典 #if ("" != $dictType)## 有数据字典
#if (!$dictMethods.contains($dictMethod))## 如果不存在,则添加到 dictMethods 数组中,后续好 import
#set($ignore = $dictMethods.add($dictMethod) )
#end
<el-option <el-option
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" :key="dict.value"
@ -63,9 +72,6 @@
<el-form-item label="${comment}" prop="${javaField}"> <el-form-item label="${comment}" prop="${javaField}">
<el-checkbox-group v-model="formData.${javaField}"> <el-checkbox-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典 #if ("" != $dictType)## 有数据字典
#if (!$dictMethods.contains($dictMethod))## 如果不存在,则添加到 dictMethods 数组中,后续好 import
#set($ignore = $dictMethods.add($dictMethod) )
#end
<el-checkbox <el-checkbox
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" :key="dict.value"
@ -82,9 +88,6 @@
<el-form-item label="${comment}" prop="${javaField}"> <el-form-item label="${comment}" prop="${javaField}">
<el-radio-group v-model="formData.${javaField}"> <el-radio-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典 #if ("" != $dictType)## 有数据字典
#if (!$dictMethods.contains($dictMethod))## 如果不存在,则添加到 dictMethods 数组中,后续好 import
#set($ignore = $dictMethods.add($dictMethod) )
#end
<el-radio <el-radio
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" :key="dict.value"
@ -114,6 +117,21 @@
#end #end
#end #end
</el-form> </el-form>
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
<!-- 子表的表单 -->
<el-tabs v-model="subTabsName">
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
<el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
<${subSimpleClassName}Form ref="${subClassNameVar}FormRef" :${subJoinColumn_strikeCase}="formData.id" />
</el-tab-pane>
#end
</el-tabs>
#end
<template #footer> <template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button> <el-button @click="dialogVisible = false">取 消</el-button>
@ -121,10 +139,18 @@
</Dialog> </Dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
#if ($dictMethods.size() > 0) import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { DICT_TYPE#foreach ($dictMethod in $dictMethods), ${dictMethod}#end } from '@/utils/dict' import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
import { defaultProps, handleTree } from '@/utils/tree'
#end
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
#foreach ($subSimpleClassName in $subSimpleClassNames)
import ${subSimpleClassName}Form from './components/${subSimpleClassName}Form.vue'
#end
#end #end
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${classNameVar}'
const { t } = useI18n() // 国际化 const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗 const message = useMessage() // 消息弹窗
@ -134,37 +160,40 @@ const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用 const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改 const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({ const formData = ref({
#set ($listOperationLastIndex = -1)## 求最后一个需要 , 的地方
#foreach ($column in $columns)
#if ($column.createOperation || $column.updateOperation)
#set ($listOperationLastIndex = $foreach.index)
#end
#end
#foreach ($column in $columns) #foreach ($column in $columns)
#if ($column.createOperation || $column.updateOperation) #if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox") #if ($column.htmlType == "checkbox")
$column.javaField: []#if($foreach.index < $listOperationLastIndex),#end $column.javaField: [],
#else #else
$column.javaField: undefined#if($foreach.index < $listOperationLastIndex),#end $column.javaField: undefined,
#end #end
#end #end
#end #end
}) })
const formRules = reactive({ const formRules = reactive({
#set ($listOperationLastIndex = -1)## 求最后一个需要 , 的地方
#foreach ($column in $columns)
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
#set ($listOperationLastIndex = $foreach.index)
#end
#end
#foreach ($column in $columns) #foreach ($column in $columns)
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键 #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
#set($comment=$column.columnComment) #set($comment=$column.columnComment)
$column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }]#if($foreach.index < $listOperationLastIndex),#end $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
#end #end
#end #end
}) })
const formRef = ref() // 表单 Ref const formRef = ref() // 表单 Ref
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
const ${classNameVar}Tree = ref() // 树形结构
#end
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
#if ( $subTables && $subTables.size() > 0 )
/** 子表的表单 */
const subTabsName = ref('$subClassNameVars.get(0)')
#foreach ($subClassNameVar in $subClassNameVars)
const ${subClassNameVar}FormRef = ref()
#end
#end
#end
/** 打开弹窗 */ /** 打开弹窗 */
const open = async (type: string, id?: number) => { const open = async (type: string, id?: number) => {
@ -181,6 +210,10 @@ const open = async (type: string, id?: number) => {
formLoading.value = false formLoading.value = false
} }
} }
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
await get${simpleClassName}Tree()
#end
} }
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 defineExpose({ open }) // 提供 open 方法,用于打开弹窗
@ -188,13 +221,38 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => { const submitForm = async () => {
// 校验表单 // 校验表单
if (!formRef) return await formRef.value.validate()
const valid = await formRef.value.validate() ## 特殊:主子表专属逻辑
if (!valid) return #if ( $table.templateType == 10 || $table.templateType == 12 )
#if ( $subTables && $subTables.size() > 0 )
// 校验子表单
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
try {
await ${subClassNameVar}FormRef.value.validate()
} catch (e) {
subTabsName.value = '${subClassNameVar}'
return
}
#end
#end
#end
// 提交请求 // 提交请求
formLoading.value = true formLoading.value = true
try { try {
const data = formData.value as unknown as ${simpleClassName}Api.${simpleClassName}VO const data = formData.value as unknown as ${simpleClassName}Api.${simpleClassName}VO
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
#if ( $subTables && $subTables.size() > 0 )
// 拼接子表的数据
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
data.${subClassNameVar}#if ( $subTable.subJoinMany)s#end = ${subClassNameVar}FormRef.value.getData()
#end
#end
#end
if (formType.value === 'create') { if (formType.value === 'create') {
await ${simpleClassName}Api.create${simpleClassName}(data) await ${simpleClassName}Api.create${simpleClassName}(data)
message.success(t('common.createSuccess')) message.success(t('common.createSuccess'))
@ -213,22 +271,28 @@ const submitForm = async () => {
/** 重置表单 */ /** 重置表单 */
const resetForm = () => { const resetForm = () => {
formData.value = { formData.value = {
#set ($listOperationLastIndex = -1)## 求最后一个需要 , 的地方
#foreach ($column in $columns)
#if ($column.createOperation || $column.updateOperation)
#set ($listOperationLastIndex = $foreach.index)
#end
#end
#foreach ($column in $columns) #foreach ($column in $columns)
#if ($column.createOperation || $column.updateOperation) #if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox") #if ($column.htmlType == "checkbox")
$column.javaField: []#if($foreach.index < $listOperationLastIndex),#end $column.javaField: [],
#else #else
$column.javaField: undefined#if($foreach.index < $listOperationLastIndex),#end $column.javaField: undefined,
#end #end
#end #end
#end #end
} }
formRef.value?.resetFields() formRef.value?.resetFields()
} }
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
/** 获得${table.classComment}树 */
const get${simpleClassName}Tree = async () => {
${classNameVar}Tree.value = []
const data = await ${simpleClassName}Api.get${simpleClassName}List()
const root: Tree = { id: 0, name: '顶级${table.classComment}', children: [] }
root.children = handleTree(data, 'id', '${treeParentColumn.javaField}')
${classNameVar}Tree.value.push(root)
}
#end
</script> </script>

View File

@ -8,7 +8,6 @@
:inline="true" :inline="true"
label-width="68px" label-width="68px"
> >
#set ($dictMethods = [])## 使用到的 dict 字典方法
#foreach($column in $columns) #foreach($column in $columns)
#if ($column.listOperation) #if ($column.listOperation)
#set ($dictType = $column.dictType) #set ($dictType = $column.dictType)
@ -36,20 +35,13 @@
</el-form-item> </el-form-item>
#elseif ($column.htmlType == "select" || $column.htmlType == "radio") #elseif ($column.htmlType == "select" || $column.htmlType == "radio")
<el-form-item label="${comment}" prop="${javaField}"> <el-form-item label="${comment}" prop="${javaField}">
#if ($javaField.length() + $comment.length() > 8)
<el-select <el-select
v-model="queryParams.${javaField}" v-model="queryParams.${javaField}"
placeholder="请选择${comment}" placeholder="请选择${comment}"
clearable clearable
class="!w-240px" class="!w-240px"
> >
#else
<el-select v-model="queryParams.${javaField}" placeholder="请选择${comment}" clearable class="!w-240px">
#end
#if ("" != $dictType)## 设置了 dictType 数据字典的情况 #if ("" != $dictType)## 设置了 dictType 数据字典的情况
#if (!$dictMethods.contains($dictMethod))## 如果不存在,则添加到 dictMethods 数组中,后续好 import
#set($ignore = $dictMethods.add($dictMethod) )
#end
<el-option <el-option
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" :key="dict.value"
@ -92,16 +84,12 @@
<el-form-item> <el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
#if ($permissionPrefix.length() <= 12)
<el-button type="primary" @click="openForm('create')" v-hasPermi="['${permissionPrefix}:create']">
#else
<el-button <el-button
type="primary" type="primary"
plain plain
@click="openForm('create')" @click="openForm('create')"
v-hasPermi="['${permissionPrefix}:create']" v-hasPermi="['${permissionPrefix}:create']"
> >
#end
<Icon icon="ep:plus" class="mr-5px" /> 新增 <Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button> </el-button>
<el-button <el-button
@ -113,13 +101,61 @@
> >
<Icon icon="ep:download" class="mr-5px" /> 导出 <Icon icon="ep:download" class="mr-5px" /> 导出
</el-button> </el-button>
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
<el-button type="danger" plain @click="toggleExpandAll">
<Icon icon="ep:sort" class="mr-5px" /> 展开/折叠
</el-button>
#end
</el-form-item> </el-form-item>
</el-form> </el-form>
</ContentWrap> </ContentWrap>
<!-- 列表 --> <!-- 列表 -->
<ContentWrap> <ContentWrap>
## 特殊:主子表专属逻辑
#if ( $table.templateType == 11 && $subTables && $subTables.size() > 0 )
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
highlight-current-row
@current-change="handleCurrentChange"
>
## 特殊:树表专属逻辑
#elseif ( $table.templateType == 2 )
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
:default-expand-all="isExpandAll"
v-if="refreshTable"
>
#else
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
#end
## 特殊:主子表专属逻辑
#if ( $table.templateType == 12 && $subTables && $subTables.size() > 0 )
<!-- 子表的列表 -->
<el-table-column type="expand">
<template #default="scope">
<el-tabs model-value="$subClassNameVars.get(0)">
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
<el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
<${subSimpleClassName}List :${subJoinColumn_strikeCase}="scope.row.id" />
</el-tab-pane>
#end
</el-tabs>
</template>
</el-table-column>
#end
#foreach($column in $columns) #foreach($column in $columns)
#if ($column.listOperationResult) #if ($column.listOperationResult)
#set ($dictType=$column.dictType) #set ($dictType=$column.dictType)
@ -134,7 +170,7 @@
:formatter="dateFormatter" :formatter="dateFormatter"
width="180px" width="180px"
/> />
#elseif("" != $column.dictType)## 数据字典 #elseif($column.dictType && "" != $column.dictType)## 数据字典
<el-table-column label="${comment}" align="center" prop="${javaField}"> <el-table-column label="${comment}" align="center" prop="${javaField}">
<template #default="scope"> <template #default="scope">
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.${column.javaField}" /> <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.${column.javaField}" />
@ -177,21 +213,41 @@
<!-- 表单弹窗:添加/修改 --> <!-- 表单弹窗:添加/修改 -->
<${simpleClassName}Form ref="formRef" @success="getList" /> <${simpleClassName}Form ref="formRef" @success="getList" />
## 特殊:主子表专属逻辑
#if ( $table.templateType == 11 && $subTables && $subTables.size() > 0 )
<!-- 子表的列表 -->
<ContentWrap>
<el-tabs model-value="$subClassNameVars.get(0)">
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
<el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
<${subSimpleClassName}List :${subJoinColumn_strikeCase}="currentRow.id" />
</el-tab-pane>
#end
</el-tabs>
</ContentWrap>
#end
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
#if ($dictMethods.size() > 0) import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { DICT_TYPE#foreach ($dictMethod in $dictMethods), ${dictMethod}#end } from '@/utils/dict'
#end
#foreach ($column in $columns)
#if ($column.listOperationResult && $column.htmlType == "datetime")
import { dateFormatter } from '@/utils/formatTime' import { dateFormatter } from '@/utils/formatTime'
#break ## 特殊:树表专属逻辑
#end #if ( $table.templateType == 2 )
import { handleTree } from '@/utils/tree'
#end #end
import download from '@/utils/download' import download from '@/utils/download'
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${classNameVar}' import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
import ${simpleClassName}Form from './${simpleClassName}Form.vue' import ${simpleClassName}Form from './${simpleClassName}Form.vue'
## 特殊:主子表专属逻辑
#if ( $table.templateType != 10 )
#foreach ($subSimpleClassName in $subSimpleClassNames)
import ${subSimpleClassName}List from './components/${subSimpleClassName}List.vue'
#end
#end
defineOptions({ name: '${table.className}' }) defineOptions({ name: '${table.className}' })
@ -199,24 +255,24 @@ const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化 const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中 const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([]) // 列表的数据 const list = ref([]) // 列表的数据
## 特殊:树表专属逻辑(树不需要分页接口)
#if ( $table.templateType != 2 )
const total = ref(0) // 列表的总页数
#end
const queryParams = reactive({ const queryParams = reactive({
## 特殊:树表专属逻辑(树不需要分页接口)
#if ( $table.templateType != 2 )
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
#set ($listOperationLastIndex = -1)## 求最后一个需要 , 的地方
#foreach ($column in $columns)
#if ($column.listOperation)
#set ($listOperationLastIndex = $foreach.index)
#end
#end #end
#foreach ($column in $columns) #foreach ($column in $columns)
#if ($column.listOperation) #if ($column.listOperation)
#if ($column.listOperationCondition != 'BETWEEN') #if ($column.listOperationCondition != 'BETWEEN')
$column.javaField: null#if($foreach.index < $listOperationLastIndex),#end $column.javaField: null,
#end #end
#if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN") #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
$column.javaField: []#if($foreach.index < $listOperationLastIndex),#end $column.javaField: [],
#end #end
#end #end
#end #end
@ -228,9 +284,15 @@ const exportLoading = ref(false) // 导出的加载中
const getList = async () => { const getList = async () => {
loading.value = true loading.value = true
try { try {
## 特殊:树表专属逻辑(树不需要分页接口)
#if ( $table.templateType == 2 )
const data = await ${simpleClassName}Api.get${simpleClassName}List(queryParams)
list.value = handleTree(data, 'id', '${treeParentColumn.javaField}')
#else
const data = await ${simpleClassName}Api.get${simpleClassName}Page(queryParams) const data = await ${simpleClassName}Api.get${simpleClassName}Page(queryParams)
list.value = data.list list.value = data.list
total.value = data.total total.value = data.total
#end
} finally { } finally {
loading.value = false loading.value = false
} }
@ -281,6 +343,28 @@ const handleExport = async () => {
exportLoading.value = false exportLoading.value = false
} }
} }
## 特殊:主子表专属逻辑
#if ( $table.templateType == 11 )
/** 选中行操作 */
const currentRow = ref({}) // 选中行
const handleCurrentChange = (row) => {
currentRow.value = row
}
#end
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
/** 展开/折叠操作 */
const isExpandAll = ref(true) // 是否展开,默认全部展开
const refreshTable = ref(true) // 重新渲染表格状态
const toggleExpandAll = async () => {
refreshTable.value = false
isExpandAll.value = !isExpandAll.value
await nextTick()
refreshTable.value = true
}
#end
/** 初始化 **/ /** 初始化 **/
onMounted(() => { onMounted(() => {

View File

@ -1,10 +1,5 @@
import type { CrudSchema } from '@/hooks/web/useCrudSchemas' import type { CrudSchema } from '@/hooks/web/useCrudSchemas'
#foreach ($column in $columns)
#if ($column.listOperationResult && $column.htmlType == "datetime")
import { dateFormatter } from '@/utils/formatTime' import { dateFormatter } from '@/utils/formatTime'
#break
#end
#end
// 表单校验 // 表单校验
export const rules = reactive({ export const rules = reactive({

View File

@ -1,5 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import {columns, searchFormSchema} from './' import ${simpleClassName}Modal from './${simpleClassName}Modal.vue'
import { columns, searchFormSchema } from './${classNameVar}.data'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage' import { useMessage } from '@/hooks/web/useMessage'
import { useModal } from '@/components/Modal' import { useModal } from '@/components/Modal'

View File

@ -1,23 +0,0 @@
package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaColumnDO;
import cn.iocoder.yudao.module.tool.test.BaseDbUnitTest;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class SchemaColumnMapperTest extends BaseDbUnitTest {
@Resource
private SchemaColumnMapper schemaColumnMapper;
@Test
public void testSelectListByTableName() {
List<SchemaColumnDO> columns = schemaColumnMapper.selectListByTableName("", "inf_config");
assertTrue(columns.size() > 0);
}
}

View File

@ -1,4 +0,0 @@
/**
*
*/
package cn.iocoder.yudao.module.infra.dal.mysql;

View File

@ -1,4 +0,0 @@
/**
*
*/
package cn.iocoder.yudao.module.infra.dal;

View File

@ -1,34 +0,0 @@
package cn.iocoder.yudao.module.infra.service.codegen;
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.dal.mysql.codegen.CodegenColumnMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper;
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine;
import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
public class CodegenEngineTest extends BaseDbUnitTest {
@Resource
private CodegenTableMapper codegenTableMapper;
@Resource
private CodegenColumnMapper codegenColumnMapper;
@Resource
private CodegenEngine codegenEngine;
@Test
public void testExecute() {
CodegenTableDO table = codegenTableMapper.selectById(20);
List<CodegenColumnDO> columns = codegenColumnMapper.selectListByTableId(table.getId());
Map<String, String> result = codegenEngine.execute(table, columns);
result.forEach((s, s2) -> System.out.println(s2));
// System.out.println(result.get("vue/views/system/test/index.vue"));
}
}

View File

@ -1,29 +0,0 @@
package cn.iocoder.yudao.module.infra.service.codegen;
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenSQLParser;
import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest;
import org.junit.jupiter.api.Test;
public class CodegenSQLParserTest extends BaseDbUnitTest {
@Test
public void testParse() {
String sql = "CREATE TABLE `infra_test_demo` (\n" +
" `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',\n" +
" `name` varchar(100) NOT NULL DEFAULT '' COMMENT '名字',\n" +
" `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态',\n" +
" `type` tinyint(4) NOT NULL COMMENT '类型',\n" +
" `category` tinyint(4) NOT NULL COMMENT '分类',\n" +
" `remark` varchar(500) DEFAULT NULL COMMENT '备注',\n" +
" `create_by` varchar(64) DEFAULT '' COMMENT '创建者',\n" +
" `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n" +
" `update_by` varchar(64) DEFAULT '' COMMENT '更新者',\n" +
" `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n" +
" `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',\n" +
" PRIMARY KEY (`id`) USING BTREE\n" +
") ENGINE=InnoDB AUTO_INCREMENT=108 DEFAULT CHARSET=utf8mb4 COMMENT='字典类型表';";
CodegenSQLParser.parse(sql);
// TODO 芋艿:后续完善断言
}
}

View File

@ -1,20 +0,0 @@
package cn.iocoder.yudao.module.infra.service.codegen;
import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
class CodegenServiceImplTest extends BaseDbUnitTest {
@Resource
private CodegenServiceImpl codegenService;
@Test
public void tetCreateCodegenTable() {
codegenService.createCodegen(0L, "infra_test_demo");
// infraCodegenService.createCodegenTable("infra_codegen_table");
// infraCodegenService.createCodegen("infra_codegen_column");
}
}

View File

@ -1,4 +0,0 @@
/**
*
*/
package cn.iocoder.yudao.module.infra.service;

View File

@ -1,38 +0,0 @@
package cn.iocoder.yudao.module.infra.test;
import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import org.redisson.spring.starter.RedissonAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisIntegrationTest.Application.class)
@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件
public class BaseDbAndRedisIntegrationTest {
@Import({
// DB 配置类
DynamicDataSourceAutoConfiguration.class, // Dynamic Datasource 配置类
YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类
DataSourceAutoConfiguration.class, // Spring DB 自动配置类
DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
// MyBatis 配置类
YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
// Redis 配置类
RedisAutoConfiguration.class, // Spring Redis 自动配置类
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
RedissonAutoConfiguration.class, // Redisson 自动高配置类
})
public static class Application {
}
}

Some files were not shown because too many files have changed in this diff Show More