Commit 067d53ac481ed2562374269422d8e13fe28a4e01

Authored by zhijiantianya@gmail.com
1 parent ee918a6d

代码生成器:增加单元测试,🛫

Showing 138 changed files with 8649 additions and 1794 deletions

Too many changes.

To preserve performance only 100 of 138 files are displayed.

yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.json; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.json;
3 import cn.hutool.core.util.ArrayUtil; 3 import cn.hutool.core.util.ArrayUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
5 import cn.hutool.json.JSONUtil; 5 import cn.hutool.json.JSONUtil;
  6 +import com.fasterxml.jackson.annotation.JsonInclude;
6 import com.fasterxml.jackson.core.type.TypeReference; 7 import com.fasterxml.jackson.core.type.TypeReference;
7 import com.fasterxml.jackson.databind.DeserializationFeature; 8 import com.fasterxml.jackson.databind.DeserializationFeature;
8 import com.fasterxml.jackson.databind.JsonNode; 9 import com.fasterxml.jackson.databind.JsonNode;
@@ -30,6 +31,7 @@ public class JsonUtils { @@ -30,6 +31,7 @@ public class JsonUtils {
30 static { 31 static {
31 objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); 32 objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
32 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 33 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
  34 + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略 null 值
33 objectMapper.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化 35 objectMapper.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化
34 } 36 }
35 37
@@ -71,6 +73,20 @@ public class JsonUtils { @@ -71,6 +73,20 @@ public class JsonUtils {
71 } 73 }
72 } 74 }
73 75
  76 + public static <T> T parseObject(String text, String path, Class<T> clazz) {
  77 + if (StrUtil.isEmpty(text)) {
  78 + return null;
  79 + }
  80 + try {
  81 + JsonNode treeNode = objectMapper.readTree(text);
  82 + JsonNode pathNode = treeNode.path(path);
  83 + return objectMapper.readValue(pathNode.toString(), clazz);
  84 + } catch (IOException e) {
  85 + log.error("json parse err,json:{}", text, e);
  86 + throw new RuntimeException(e);
  87 + }
  88 + }
  89 +
74 public static <T> T parseObject(String text, Type type) { 90 public static <T> T parseObject(String text, Type type) {
75 if (StrUtil.isEmpty(text)) { 91 if (StrUtil.isEmpty(text)) {
76 return null; 92 return null;
@@ -132,6 +148,20 @@ public class JsonUtils { @@ -132,6 +148,20 @@ public class JsonUtils {
132 } 148 }
133 } 149 }
134 150
  151 + public static <T> List<T> parseArray(String text, String path, Class<T> clazz) {
  152 + if (StrUtil.isEmpty(text)) {
  153 + return null;
  154 + }
  155 + try {
  156 + JsonNode treeNode = objectMapper.readTree(text);
  157 + JsonNode pathNode = treeNode.path(path);
  158 + return objectMapper.readValue(pathNode.toString(), objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
  159 + } catch (IOException e) {
  160 + log.error("json parse err,json:{}", text, e);
  161 + throw new RuntimeException(e);
  162 + }
  163 + }
  164 +
135 public static JsonNode parseTree(String text) { 165 public static JsonNode parseTree(String text) {
136 try { 166 try {
137 return objectMapper.readTree(text); 167 return objectMapper.readTree(text);
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/saveReqVO.vm
@@ -49,13 +49,14 @@ public class ${sceneEnum.prefixClass}${table.className}SaveReqVO { @@ -49,13 +49,14 @@ public class ${sceneEnum.prefixClass}${table.className}SaveReqVO {
49 #end 49 #end
50 ## 特殊:主子表专属逻辑(非 ERP 模式) 50 ## 特殊:主子表专属逻辑(非 ERP 模式)
51 #if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 ) 51 #if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
52 -  
53 #foreach ($subTable in $subTables) 52 #foreach ($subTable in $subTables)
54 #set ($index = $foreach.count - 1) 53 #set ($index = $foreach.count - 1)
55 #if ( $subTable.subJoinMany) 54 #if ( $subTable.subJoinMany)
  55 + @Schema(description = "${subTable.classComment}列表")
56 private List<${subTable.className}DO> ${subClassNameVars.get($index)}s; 56 private List<${subTable.className}DO> ${subClassNameVars.get($index)}s;
57 57
58 #else 58 #else
  59 + @Schema(description = "${subTable.classComment}")
59 private ${subTable.className}DO ${subClassNameVars.get($index)}; 60 private ${subTable.className}DO ${subClassNameVars.get($index)};
60 61
61 #end 62 #end
yudao-module-infra/yudao-module-infra-biz/src/test-integration/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaColumnMapperTest.java deleted
1 -package cn.iocoder.yudao.module.infra.dal.mysql.codegen;  
2 -  
3 -import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaColumnDO;  
4 -import cn.iocoder.yudao.module.tool.test.BaseDbUnitTest;  
5 -import org.junit.jupiter.api.Test;  
6 -  
7 -import javax.annotation.Resource;  
8 -import java.util.List;  
9 -  
10 -import static org.junit.jupiter.api.Assertions.assertTrue;  
11 -  
12 -public class SchemaColumnMapperTest extends BaseDbUnitTest {  
13 -  
14 - @Resource  
15 - private SchemaColumnMapper schemaColumnMapper;  
16 -  
17 - @Test  
18 - public void testSelectListByTableName() {  
19 - List<SchemaColumnDO> columns = schemaColumnMapper.selectListByTableName("", "inf_config");  
20 - assertTrue(columns.size() > 0);  
21 - }  
22 -  
23 -}  
yudao-module-infra/yudao-module-infra-biz/src/test-integration/java/cn/iocoder/yudao/module/infra/dal/mysql/package-info.java deleted
1 -/**  
2 - * 占位  
3 - */  
4 -package cn.iocoder.yudao.module.infra.dal.mysql;  
yudao-module-infra/yudao-module-infra-biz/src/test-integration/java/cn/iocoder/yudao/module/infra/dal/package-info.java deleted
1 -/**  
2 - * 占位  
3 - */  
4 -package cn.iocoder.yudao.module.infra.dal;  
yudao-module-infra/yudao-module-infra-biz/src/test-integration/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenEngineTest.java deleted
1 -package cn.iocoder.yudao.module.infra.service.codegen;  
2 -  
3 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;  
4 -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;  
5 -import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper;  
6 -import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper;  
7 -import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine;  
8 -import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest;  
9 -import org.junit.jupiter.api.Test;  
10 -  
11 -import javax.annotation.Resource;  
12 -import java.util.List;  
13 -import java.util.Map;  
14 -  
15 -public class CodegenEngineTest extends BaseDbUnitTest {  
16 -  
17 - @Resource  
18 - private CodegenTableMapper codegenTableMapper;  
19 - @Resource  
20 - private CodegenColumnMapper codegenColumnMapper;  
21 -  
22 - @Resource  
23 - private CodegenEngine codegenEngine;  
24 -  
25 - @Test  
26 - public void testExecute() {  
27 - CodegenTableDO table = codegenTableMapper.selectById(20);  
28 - List<CodegenColumnDO> columns = codegenColumnMapper.selectListByTableId(table.getId());  
29 - Map<String, String> result = codegenEngine.execute(table, columns);  
30 - result.forEach((s, s2) -> System.out.println(s2));  
31 -// System.out.println(result.get("vue/views/system/test/index.vue"));  
32 - }  
33 -  
34 -}  
yudao-module-infra/yudao-module-infra-biz/src/test-integration/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenSQLParserTest.java deleted
1 -package cn.iocoder.yudao.module.infra.service.codegen;  
2 -  
3 -import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenSQLParser;  
4 -import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest;  
5 -import org.junit.jupiter.api.Test;  
6 -  
7 -public class CodegenSQLParserTest extends BaseDbUnitTest {  
8 -  
9 - @Test  
10 - public void testParse() {  
11 - String sql = "CREATE TABLE `infra_test_demo` (\n" +  
12 - " `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',\n" +  
13 - " `name` varchar(100) NOT NULL DEFAULT '' COMMENT '名字',\n" +  
14 - " `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态',\n" +  
15 - " `type` tinyint(4) NOT NULL COMMENT '类型',\n" +  
16 - " `category` tinyint(4) NOT NULL COMMENT '分类',\n" +  
17 - " `remark` varchar(500) DEFAULT NULL COMMENT '备注',\n" +  
18 - " `create_by` varchar(64) DEFAULT '' COMMENT '创建者',\n" +  
19 - " `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n" +  
20 - " `update_by` varchar(64) DEFAULT '' COMMENT '更新者',\n" +  
21 - " `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n" +  
22 - " `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',\n" +  
23 - " PRIMARY KEY (`id`) USING BTREE\n" +  
24 - ") ENGINE=InnoDB AUTO_INCREMENT=108 DEFAULT CHARSET=utf8mb4 COMMENT='字典类型表';";  
25 - CodegenSQLParser.parse(sql);  
26 - // TODO 芋艿:后续完善断言  
27 - }  
28 -  
29 -}  
yudao-module-infra/yudao-module-infra-biz/src/test-integration/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImplTest.java deleted
1 -package cn.iocoder.yudao.module.infra.service.codegen;  
2 -  
3 -import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest;  
4 -import org.junit.jupiter.api.Test;  
5 -  
6 -import javax.annotation.Resource;  
7 -  
8 -class CodegenServiceImplTest extends BaseDbUnitTest {  
9 -  
10 - @Resource  
11 - private CodegenServiceImpl codegenService;  
12 -  
13 - @Test  
14 - public void tetCreateCodegenTable() {  
15 - codegenService.createCodegen(0L, "infra_test_demo");  
16 -// infraCodegenService.createCodegenTable("infra_codegen_table");  
17 -// infraCodegenService.createCodegen("infra_codegen_column");  
18 - }  
19 -  
20 -}  
yudao-module-infra/yudao-module-infra-biz/src/test-integration/java/cn/iocoder/yudao/module/infra/service/package-info.java deleted
1 -/**  
2 - * 占位  
3 - */  
4 -package cn.iocoder.yudao.module.infra.service;  
yudao-module-infra/yudao-module-infra-biz/src/test-integration/java/cn/iocoder/yudao/module/infra/test/BaseDbAndRedisIntegrationTest.java deleted
1 -package cn.iocoder.yudao.module.infra.test;  
2 -  
3 -import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;  
4 -import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;  
5 -import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;  
6 -import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;  
7 -import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;  
8 -import org.redisson.spring.starter.RedissonAutoConfiguration;  
9 -import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;  
10 -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;  
11 -import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;  
12 -import org.springframework.boot.test.context.SpringBootTest;  
13 -import org.springframework.context.annotation.Import;  
14 -import org.springframework.test.context.ActiveProfiles;  
15 -  
16 -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisIntegrationTest.Application.class)  
17 -@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件  
18 -public class BaseDbAndRedisIntegrationTest {  
19 -  
20 - @Import({  
21 - // DB 配置类  
22 - DynamicDataSourceAutoConfiguration.class, // Dynamic Datasource 配置类  
23 - YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类  
24 - DataSourceAutoConfiguration.class, // Spring DB 自动配置类  
25 - DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类  
26 - // MyBatis 配置类  
27 - YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类  
28 - MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类  
29 -  
30 - // Redis 配置类  
31 - RedisAutoConfiguration.class, // Spring Redis 自动配置类  
32 - YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类  
33 - RedissonAutoConfiguration.class, // Redisson 自动高配置类  
34 - })  
35 - public static class Application {  
36 - }  
37 -  
38 -}  
yudao-module-infra/yudao-module-infra-biz/src/test-integration/java/cn/iocoder/yudao/module/infra/test/BaseRedisIntegrationTest.java deleted
1 -package cn.iocoder.yudao.module.infra.test;  
2 -  
3 -import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;  
4 -import org.redisson.spring.starter.RedissonAutoConfiguration;  
5 -import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;  
6 -import org.springframework.boot.test.context.SpringBootTest;  
7 -import org.springframework.context.annotation.Import;  
8 -import org.springframework.test.context.ActiveProfiles;  
9 -  
10 -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseRedisIntegrationTest.Application.class)  
11 -@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件  
12 -public class BaseRedisIntegrationTest {  
13 -  
14 - @Import({  
15 - // Redis 配置类  
16 - RedisAutoConfiguration.class, // Spring Redis 自动配置类  
17 - YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类  
18 - RedissonAutoConfiguration.class, // Redisson 自动高配置类  
19 - })  
20 - public static class Application {  
21 - }  
22 -  
23 -}  
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineTest.java
@@ -3,7 +3,10 @@ package cn.iocoder.yudao.module.infra.service.codegen.inner; @@ -3,7 +3,10 @@ package cn.iocoder.yudao.module.infra.service.codegen.inner;
3 import cn.hutool.core.io.FileUtil; 3 import cn.hutool.core.io.FileUtil;
4 import cn.hutool.core.io.IoUtil; 4 import cn.hutool.core.io.IoUtil;
5 import cn.hutool.core.io.resource.ResourceUtil; 5 import cn.hutool.core.io.resource.ResourceUtil;
  6 +import cn.hutool.core.map.MapUtil;
  7 +import cn.hutool.core.util.StrUtil;
6 import cn.hutool.core.util.ZipUtil; 8 import cn.hutool.core.util.ZipUtil;
  9 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
7 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; 10 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
8 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; 11 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
9 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; 12 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
@@ -17,11 +20,10 @@ import org.mockito.Spy; @@ -17,11 +20,10 @@ import org.mockito.Spy;
17 20
18 import java.io.ByteArrayInputStream; 21 import java.io.ByteArrayInputStream;
19 import java.io.ByteArrayOutputStream; 22 import java.io.ByteArrayOutputStream;
20 -import java.util.Arrays;  
21 -import java.util.List;  
22 -import java.util.Map; 23 +import java.util.*;
23 24
24 import static org.junit.jupiter.api.Assertions.assertEquals; 25 import static org.junit.jupiter.api.Assertions.assertEquals;
  26 +import static org.junit.jupiter.api.Assertions.assertTrue;
25 27
26 /** 28 /**
27 * {@link CodegenEngine} 的单元测试 29 * {@link CodegenEngine} 的单元测试
@@ -43,759 +45,126 @@ public class CodegenEngineTest extends BaseMockitoUnitTest { @@ -43,759 +45,126 @@ public class CodegenEngineTest extends BaseMockitoUnitTest {
43 } 45 }
44 46
45 @Test 47 @Test
46 - public void testExecute_vue3_tree() {  
47 - // 准备请求参数  
48 - CodegenTableDO table = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene()).setParentMenuId(888L)  
49 - .setTableName("infra_demo66_student").setTableComment("学生表")  
50 - .setModuleName("infra").setBusinessName("demo66").setClassName("InfraDemo66Student")  
51 - .setClassComment("学生").setAuthor("芋道源码")  
52 - .setTemplateType(CodegenTemplateTypeEnum.TREE.getType()) 48 + public void testExecute_vue3_one() {
  49 + // 准备参数
  50 + CodegenTableDO table = getTable("student")
53 .setFrontType(CodegenFrontTypeEnum.VUE3.getType()) 51 .setFrontType(CodegenFrontTypeEnum.VUE3.getType())
54 - .setTreeParentColumnId(22L).setTreeNameColumnId(11L);  
55 - CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())  
56 - .setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)  
57 - .setJavaType("Long").setJavaField("id").setExample("1024")  
58 - .setCreateOperation(false).setUpdateOperation(true)  
59 - .setListOperation(false)  
60 - .setListOperationResult(true);  
61 - CodegenColumnDO nameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())  
62 - .setId(11L)  
63 - .setColumnComment("名字").setNullable(false)  
64 - .setJavaType("String").setJavaField("name").setExample("芋头")  
65 - .setCreateOperation(true).setUpdateOperation(true)  
66 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())  
67 - .setListOperationResult(true)  
68 - .setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());  
69 - CodegenColumnDO parentIdColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())  
70 - .setId(22L)  
71 - .setColumnComment("父编号").setNullable(false)  
72 - .setJavaType("Long").setJavaField("parentId").setExample("2048")  
73 - .setCreateOperation(true).setUpdateOperation(true)  
74 - .setListOperation(false)  
75 - .setListOperationResult(true);  
76 - List<CodegenColumnDO> columns = Arrays.asList(idColumn, nameColumn, parentIdColumn); 52 + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType());
  53 + List<CodegenColumnDO> columns = getColumnList("student");
77 54
78 // 调用 55 // 调用
79 Map<String, String> result = codegenEngine.execute(table, columns, null, null); 56 Map<String, String> result = codegenEngine.execute(table, columns, null, null);
80 -  
81 - // 构建 zip 包  
82 - writeFile(result, "/Users/yunai/test/demo66.zip"); 57 + // 断言
  58 + assertResult(result, "codegen/vue3_one");
  59 +// writeResult(result, "/root/ruoyi-vue-pro/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one");
83 } 60 }
84 61
85 @Test 62 @Test
86 - public void testExecute_vue3_crud() {  
87 - // 准备请求参数  
88 - CodegenTableDO table = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene()).setParentMenuId(888L)  
89 - .setTableName("infra_demo01_student").setTableComment("学生表")  
90 - .setModuleName("infra").setBusinessName("demo01").setClassName("InfraDemo01Student")  
91 - .setClassComment("学生").setAuthor("芋道源码")  
92 - .setTemplateType(CodegenTemplateTypeEnum.ONE.getType())  
93 - .setFrontType(CodegenFrontTypeEnum.VUE3.getType());  
94 - CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())  
95 - .setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)  
96 - .setJavaType("Long").setJavaField("id").setExample("1024")  
97 - .setCreateOperation(false).setUpdateOperation(true)  
98 - .setListOperation(false)  
99 - .setListOperationResult(true);  
100 - CodegenColumnDO nameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())  
101 - .setColumnComment("名字").setNullable(false)  
102 - .setJavaType("String").setJavaField("name").setExample("芋头")  
103 - .setCreateOperation(true).setUpdateOperation(true)  
104 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())  
105 - .setListOperationResult(true)  
106 - .setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());  
107 - CodegenColumnDO descriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())  
108 - .setColumnComment("简介").setNullable(false)  
109 - .setJavaType("String").setJavaField("description").setExample("我是介绍")  
110 - .setCreateOperation(true).setUpdateOperation(true)  
111 - .setListOperation(false)  
112 - .setListOperationResult(true)  
113 - .setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());  
114 - CodegenColumnDO birthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())  
115 - .setColumnComment("出生日期").setNullable(false)  
116 - .setJavaType("LocalDateTime").setJavaField("birthday")  
117 - .setCreateOperation(true).setUpdateOperation(true)  
118 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
119 - .setListOperationResult(true)  
120 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
121 - CodegenColumnDO sexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())  
122 - .setColumnComment("性别").setNullable(false)  
123 - .setJavaType("Integer").setJavaField("sex").setExample("1")  
124 - .setCreateOperation(true).setUpdateOperation(true)  
125 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
126 - .setListOperationResult(true)  
127 - .setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())  
128 - .setDictType("system_user_sex");  
129 - CodegenColumnDO enabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())  
130 - .setColumnComment("是否有效").setNullable(false)  
131 - .setJavaType("Boolean").setJavaField("enabled").setExample("true")  
132 - .setCreateOperation(true).setUpdateOperation(true)  
133 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
134 - .setListOperationResult(true)  
135 - .setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())  
136 - .setDictType("infra_boolean_string");  
137 - CodegenColumnDO avatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())  
138 - .setColumnComment("头像").setNullable(false)  
139 - .setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")  
140 - .setCreateOperation(true).setUpdateOperation(true)  
141 - .setListOperation(false)  
142 - .setListOperationResult(true)  
143 - .setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());  
144 - CodegenColumnDO videoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())  
145 - .setColumnComment("附件").setNullable(true)  
146 - .setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")  
147 - .setCreateOperation(true).setUpdateOperation(true)  
148 - .setListOperation(false)  
149 - .setListOperationResult(true)  
150 - .setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());  
151 - CodegenColumnDO memoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())  
152 - .setColumnComment("备注").setNullable(false)  
153 - .setJavaType("String").setJavaField("memo").setExample("我是备注")  
154 - .setCreateOperation(true).setUpdateOperation(true)  
155 - .setListOperation(false)  
156 - .setListOperationResult(true)  
157 - .setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());  
158 - CodegenColumnDO createTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())  
159 - .setColumnComment("创建时间").setNullable(true)  
160 - .setJavaType("LocalDateTime").setJavaField("createTime")  
161 - .setCreateOperation(false).setUpdateOperation(false)  
162 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())  
163 - .setListOperationResult(true)  
164 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
165 - List<CodegenColumnDO> columns = Arrays.asList(idColumn, nameColumn, descriptionColumn, birthdayColumn,  
166 - sexColumn, enabledColumn, avatarColumn, videoColumn, memoColumn, createTimeColumn); 63 + public void testExecute_vue3_tree() {
  64 + // 准备参数
  65 + CodegenTableDO table = getTable("category")
  66 + .setFrontType(CodegenFrontTypeEnum.VUE3.getType())
  67 + .setTemplateType(CodegenTemplateTypeEnum.TREE.getType());
  68 + List<CodegenColumnDO> columns = getColumnList("category");
167 69
168 // 调用 70 // 调用
169 Map<String, String> result = codegenEngine.execute(table, columns, null, null); 71 Map<String, String> result = codegenEngine.execute(table, columns, null, null);
170 -  
171 - // 构建 zip 包  
172 - writeFile(result, "/Users/yunai/test/demo01.zip");  
173 -  
174 // 断言 72 // 断言
175 - assertEquals(21, result.size());  
176 - // 断言 vo 类  
177 - for (String vo : new String[]{"SystemUserBaseVO", "SystemUserCreateReqVO", "SystemUserUpdateReqVO", "SystemUserRespVO",  
178 - "SystemUserPageReqVO", "SystemUserExportReqVO", "SystemUserExcelVO"}) {  
179 - assertPathContentEquals("vue3_crud/java/" + vo,  
180 - result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/" + vo + ".java");  
181 - }  
182 - // 断言 controller 类  
183 - assertPathContentEquals("vue3_crud/java/SystemUserController",  
184 - result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/SystemUserController.java");  
185 - // 断言 service 类  
186 - assertPathContentEquals("vue3_crud/java/SystemUserService",  
187 - result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/SystemUserService.java");  
188 - assertPathContentEquals("vue3_crud/java/SystemUserServiceImpl",  
189 - result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/SystemUserServiceImpl.java");  
190 - // 断言 convert 类  
191 - assertPathContentEquals("vue3_crud/java/SystemUserConvert",  
192 - result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/user/SystemUserConvert.java");  
193 - // 断言 enums 类  
194 - assertPathContentEquals("vue3_crud/java/ErrorCodeConstants",  
195 - result, "yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants_手动操作.java");  
196 - // 断言 dal 类  
197 - assertPathContentEquals("vue3_crud/java/SystemUserDO",  
198 - result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/SystemUserDO.java");  
199 - assertPathContentEquals("vue3_crud/java/SystemUserMapper",  
200 - result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/SystemUserMapper.java");  
201 - assertPathContentEquals("vue3_crud/java/SystemUserMapper_xml",  
202 - result, "yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/user/SystemUserMapper.xml");  
203 - // 断言 test 类  
204 - assertPathContentEquals("vue3_crud/java/SystemUserServiceImplTest",  
205 - result, "yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/SystemUserServiceImplTest.java");  
206 - // 断言 sql 语句  
207 - assertPathContentEquals("vue3_crud/sql/h2",  
208 - result, "sql/h2.sql");  
209 - assertPathContentEquals("vue3_crud/sql/sql",  
210 - result, "sql/sql.sql");  
211 - // 断言 vue 语句  
212 - assertPathContentEquals("vue3_crud/vue/index",  
213 - result, "yudao-ui-admin-vue3/src/views/system/user/index.vue");  
214 - assertPathContentEquals("vue3_crud/vue/form",  
215 - result, "yudao-ui-admin-vue3/src/views/system/user/UserForm.vue");  
216 - assertPathContentEquals("vue3_crud/vue/api",  
217 - result, "yudao-ui-admin-vue3/src/api/system/user/index.ts"); 73 + assertResult(result, "codegen/vue3_tree");
  74 +// writeResult(result, "/root/ruoyi-vue-pro/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree");
  75 +// writeFile(result, "/Users/yunai/test/demo66.zip");
218 } 76 }
219 77
220 @Test 78 @Test
221 - public void testExecute_vue3_masterNormal() {  
222 - // 准备请求参数  
223 - // 主表  
224 - CodegenTableDO table = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene()).setParentMenuId(888L)  
225 - .setTableName("infra_demo11_student").setTableComment("学生表")  
226 - .setModuleName("infra").setBusinessName("demo11").setClassName("InfraDemo11Student")  
227 - .setClassComment("学生").setAuthor("芋道源码")  
228 - .setTemplateType(CodegenTemplateTypeEnum.MASTER_NORMAL.getType())  
229 - .setFrontType(CodegenFrontTypeEnum.VUE3.getType());  
230 - CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())  
231 - .setId(100L)  
232 - .setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)  
233 - .setJavaType("Long").setJavaField("id").setExample("1024")  
234 - .setCreateOperation(false).setUpdateOperation(true)  
235 - .setListOperation(false)  
236 - .setListOperationResult(true);  
237 - CodegenColumnDO nameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())  
238 - .setColumnComment("名字").setNullable(false)  
239 - .setJavaType("String").setJavaField("name").setExample("芋头")  
240 - .setCreateOperation(true).setUpdateOperation(true)  
241 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())  
242 - .setListOperationResult(true)  
243 - .setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());  
244 - CodegenColumnDO descriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())  
245 - .setColumnComment("简介").setNullable(false)  
246 - .setJavaType("String").setJavaField("description").setExample("我是介绍")  
247 - .setCreateOperation(true).setUpdateOperation(true)  
248 - .setListOperation(false)  
249 - .setListOperationResult(true)  
250 - .setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());  
251 - CodegenColumnDO birthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())  
252 - .setColumnComment("出生日期").setNullable(false)  
253 - .setJavaType("LocalDateTime").setJavaField("birthday")  
254 - .setCreateOperation(true).setUpdateOperation(true)  
255 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
256 - .setListOperationResult(true)  
257 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
258 - CodegenColumnDO sexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())  
259 - .setColumnComment("性别").setNullable(false)  
260 - .setJavaType("Integer").setJavaField("sex").setExample("1")  
261 - .setCreateOperation(true).setUpdateOperation(true)  
262 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
263 - .setListOperationResult(true)  
264 - .setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())  
265 - .setDictType("system_user_sex");  
266 - CodegenColumnDO enabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())  
267 - .setColumnComment("是否有效").setNullable(false)  
268 - .setJavaType("Boolean").setJavaField("enabled").setExample("true")  
269 - .setCreateOperation(true).setUpdateOperation(true)  
270 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
271 - .setListOperationResult(true)  
272 - .setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())  
273 - .setDictType("infra_boolean_string");  
274 - CodegenColumnDO avatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())  
275 - .setColumnComment("头像").setNullable(false)  
276 - .setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")  
277 - .setCreateOperation(true).setUpdateOperation(true)  
278 - .setListOperation(false)  
279 - .setListOperationResult(true)  
280 - .setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());  
281 - CodegenColumnDO videoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())  
282 - .setColumnComment("附件").setNullable(true)  
283 - .setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")  
284 - .setCreateOperation(true).setUpdateOperation(true)  
285 - .setListOperation(false)  
286 - .setListOperationResult(true)  
287 - .setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());  
288 - CodegenColumnDO memoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())  
289 - .setColumnComment("备注").setNullable(false)  
290 - .setJavaType("String").setJavaField("memo").setExample("我是备注")  
291 - .setCreateOperation(true).setUpdateOperation(true)  
292 - .setListOperation(false)  
293 - .setListOperationResult(true)  
294 - .setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());  
295 - CodegenColumnDO createTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())  
296 - .setColumnComment("创建时间").setNullable(true)  
297 - .setJavaType("LocalDateTime").setJavaField("createTime")  
298 - .setCreateOperation(false).setUpdateOperation(false)  
299 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())  
300 - .setListOperationResult(true)  
301 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
302 - List<CodegenColumnDO> columns = Arrays.asList(idColumn, nameColumn, descriptionColumn, birthdayColumn,  
303 - sexColumn, enabledColumn, avatarColumn, videoColumn, memoColumn, createTimeColumn);  
304 -  
305 - // 子表(联系人)  
306 - CodegenTableDO contactTable = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene())  
307 - .setTableName("infra_demo11_student_contact").setTableComment("学生联系人表")  
308 - .setModuleName("infra").setBusinessName("demo11").setClassName("InfraDemo11StudentContact")  
309 - .setClassComment("学生联系人").setAuthor("芋道源码")  
310 - .setTemplateType(CodegenTemplateTypeEnum.SUB.getType())  
311 - .setFrontType(CodegenFrontTypeEnum.VUE3.getType())  
312 - .setSubJoinColumnId(100L).setSubJoinMany(true);  
313 - CodegenColumnDO contactIdColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())  
314 - .setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)  
315 - .setJavaType("Long").setJavaField("id").setExample("1024")  
316 - .setCreateOperation(false).setUpdateOperation(true)  
317 - .setListOperation(false)  
318 - .setListOperationResult(true);  
319 - CodegenColumnDO contactStudentIdColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name())  
320 - .setColumnComment("学生编号").setNullable(false).setPrimaryKey(false)  
321 - .setJavaType("Long").setJavaField("studentId").setExample("2048")  
322 - .setCreateOperation(true).setUpdateOperation(true)  
323 - .setListOperation(false)  
324 - .setListOperationResult(true)  
325 - .setId(100L);  
326 - CodegenColumnDO contactNameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())  
327 - .setColumnComment("名字").setNullable(false)  
328 - .setJavaType("String").setJavaField("name").setExample("芋头")  
329 - .setCreateOperation(true).setUpdateOperation(true)  
330 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())  
331 - .setListOperationResult(true)  
332 - .setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());  
333 - CodegenColumnDO contactDescriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())  
334 - .setColumnComment("简介").setNullable(false)  
335 - .setJavaType("String").setJavaField("description").setExample("我是介绍")  
336 - .setCreateOperation(true).setUpdateOperation(true)  
337 - .setListOperation(false)  
338 - .setListOperationResult(true)  
339 - .setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());  
340 - CodegenColumnDO contactBirthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())  
341 - .setColumnComment("出生日期").setNullable(false)  
342 - .setJavaType("LocalDateTime").setJavaField("birthday")  
343 - .setCreateOperation(true).setUpdateOperation(true)  
344 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
345 - .setListOperationResult(true)  
346 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
347 - CodegenColumnDO contactSexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())  
348 - .setColumnComment("性别").setNullable(false)  
349 - .setJavaType("Integer").setJavaField("sex").setExample("1")  
350 - .setCreateOperation(true).setUpdateOperation(true)  
351 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
352 - .setListOperationResult(true)  
353 - .setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())  
354 - .setDictType("system_user_sex");  
355 - CodegenColumnDO contactEnabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())  
356 - .setColumnComment("是否有效").setNullable(false)  
357 - .setJavaType("Boolean").setJavaField("enabled").setExample("true")  
358 - .setCreateOperation(true).setUpdateOperation(true)  
359 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
360 - .setListOperationResult(true)  
361 - .setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())  
362 - .setDictType("infra_boolean_string");  
363 - CodegenColumnDO contactAvatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())  
364 - .setColumnComment("头像").setNullable(false)  
365 - .setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")  
366 - .setCreateOperation(true).setUpdateOperation(true)  
367 - .setListOperation(false)  
368 - .setListOperationResult(true)  
369 - .setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());  
370 - CodegenColumnDO contactVideoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())  
371 - .setColumnComment("附件").setNullable(true)  
372 - .setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")  
373 - .setCreateOperation(true).setUpdateOperation(true)  
374 - .setListOperation(false)  
375 - .setListOperationResult(true)  
376 - .setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());  
377 - CodegenColumnDO contactMemoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())  
378 - .setColumnComment("备注").setNullable(false)  
379 - .setJavaType("String").setJavaField("memo").setExample("我是备注")  
380 - .setCreateOperation(true).setUpdateOperation(true)  
381 - .setListOperation(false)  
382 - .setListOperationResult(true)  
383 - .setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());  
384 - CodegenColumnDO contactCreateTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())  
385 - .setColumnComment("创建时间").setNullable(true)  
386 - .setJavaType("LocalDateTime").setJavaField("createTime")  
387 - .setCreateOperation(false).setUpdateOperation(false)  
388 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())  
389 - .setListOperationResult(true)  
390 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
391 - List<CodegenColumnDO> contactColumns = Arrays.asList(contactIdColumn, contactStudentIdColumn,  
392 - contactNameColumn, contactDescriptionColumn, contactBirthdayColumn,  
393 - contactSexColumn, contactEnabledColumn, contactAvatarColumn, contactVideoColumn, contactMemoColumn, contactCreateTimeColumn);  
394 -  
395 - // 子表(班主任)  
396 - CodegenTableDO teacherTable = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene())  
397 - .setTableName("infra_demo11_student_teacher").setTableComment("学生班主任表")  
398 - .setModuleName("infra").setBusinessName("demo11").setClassName("InfraDemo11StudentTeacher")  
399 - .setClassComment("学生班主任").setAuthor("芋道源码")  
400 - .setTemplateType(CodegenTemplateTypeEnum.SUB.getType())  
401 - .setFrontType(CodegenFrontTypeEnum.VUE3.getType())  
402 - .setSubJoinColumnId(200L).setSubJoinMany(false);  
403 - CodegenColumnDO teacherIdColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())  
404 - .setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)  
405 - .setJavaType("Long").setJavaField("id").setExample("1024")  
406 - .setCreateOperation(false).setUpdateOperation(true)  
407 - .setListOperation(false)  
408 - .setListOperationResult(true);  
409 - CodegenColumnDO teacherStudentIdColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name())  
410 - .setColumnComment("学生编号").setNullable(false).setPrimaryKey(false)  
411 - .setJavaType("Long").setJavaField("studentId").setExample("2048")  
412 - .setCreateOperation(true).setUpdateOperation(true)  
413 - .setListOperation(false)  
414 - .setListOperationResult(true)  
415 - .setId(200L);  
416 - CodegenColumnDO teacherNameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())  
417 - .setColumnComment("名字").setNullable(false)  
418 - .setJavaType("String").setJavaField("name").setExample("芋头")  
419 - .setCreateOperation(true).setUpdateOperation(true)  
420 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())  
421 - .setListOperationResult(true)  
422 - .setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());  
423 - CodegenColumnDO teacherDescriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())  
424 - .setColumnComment("简介").setNullable(false)  
425 - .setJavaType("String").setJavaField("description").setExample("我是介绍")  
426 - .setCreateOperation(true).setUpdateOperation(true)  
427 - .setListOperation(false)  
428 - .setListOperationResult(true)  
429 - .setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());  
430 - CodegenColumnDO teacherBirthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())  
431 - .setColumnComment("出生日期").setNullable(false)  
432 - .setJavaType("LocalDateTime").setJavaField("birthday")  
433 - .setCreateOperation(true).setUpdateOperation(true)  
434 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
435 - .setListOperationResult(true)  
436 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
437 - CodegenColumnDO teacherSexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())  
438 - .setColumnComment("性别").setNullable(false)  
439 - .setJavaType("Integer").setJavaField("sex").setExample("1")  
440 - .setCreateOperation(true).setUpdateOperation(true)  
441 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
442 - .setListOperationResult(true)  
443 - .setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())  
444 - .setDictType("system_user_sex");  
445 - CodegenColumnDO teacherEnabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())  
446 - .setColumnComment("是否有效").setNullable(false)  
447 - .setJavaType("Boolean").setJavaField("enabled").setExample("true")  
448 - .setCreateOperation(true).setUpdateOperation(true)  
449 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
450 - .setListOperationResult(true)  
451 - .setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())  
452 - .setDictType("infra_boolean_string");  
453 - CodegenColumnDO teacherAvatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())  
454 - .setColumnComment("头像").setNullable(false)  
455 - .setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")  
456 - .setCreateOperation(true).setUpdateOperation(true)  
457 - .setListOperation(false)  
458 - .setListOperationResult(true)  
459 - .setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());  
460 - CodegenColumnDO teacherVideoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())  
461 - .setColumnComment("附件").setNullable(true)  
462 - .setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")  
463 - .setCreateOperation(true).setUpdateOperation(true)  
464 - .setListOperation(false)  
465 - .setListOperationResult(true)  
466 - .setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());  
467 - CodegenColumnDO teacherMemoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())  
468 - .setColumnComment("备注").setNullable(false)  
469 - .setJavaType("String").setJavaField("memo").setExample("我是备注")  
470 - .setCreateOperation(true).setUpdateOperation(true)  
471 - .setListOperation(false)  
472 - .setListOperationResult(true)  
473 - .setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());  
474 - CodegenColumnDO teacherCreateTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())  
475 - .setColumnComment("创建时间").setNullable(true)  
476 - .setJavaType("LocalDateTime").setJavaField("createTime")  
477 - .setCreateOperation(false).setUpdateOperation(false)  
478 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())  
479 - .setListOperationResult(true)  
480 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
481 - List<CodegenColumnDO> teacherColumns = Arrays.asList(teacherIdColumn, teacherStudentIdColumn,  
482 - teacherNameColumn, teacherDescriptionColumn, teacherBirthdayColumn,  
483 - teacherSexColumn, teacherEnabledColumn, teacherAvatarColumn, teacherVideoColumn, teacherMemoColumn, teacherCreateTimeColumn);  
484 -  
485 - // 调用  
486 - Map<String, String> result = codegenEngine.execute(table, columns,  
487 - Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns));  
488 -  
489 - // 构建 zip 包  
490 - writeFile(result, "/Users/yunai/test/demo11.zip");  
491 -  
492 - // 断言  
493 - assertEquals(27, result.size()); 79 + public void testExecute_vue3_master_normal() {
  80 + testExecute_vue3_master(CodegenTemplateTypeEnum.MASTER_NORMAL, "codegen/vue3_master_normal");
  81 + }
494 82
495 - for (Map.Entry<String, String> entry : result.entrySet()) {  
496 - System.out.println(entry.getKey());  
497 - System.out.println(entry.getValue());  
498 - System.out.println("");  
499 - System.out.println("");  
500 - System.out.println("");  
501 - } 83 + @Test
  84 + public void testExecute_vue3_master_erp() {
  85 + testExecute_vue3_master(CodegenTemplateTypeEnum.MASTER_ERP, "codegen/vue3_master_erp");
502 } 86 }
503 87
504 @Test 88 @Test
505 - public void testExecute_vue3_masterInner() {  
506 - // 准备请求参数  
507 - // 主表  
508 - CodegenTableDO table = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene()).setParentMenuId(888L)  
509 - .setTableName("infra_demo12_student").setTableComment("学生表")  
510 - .setModuleName("infra").setBusinessName("demo12").setClassName("InfraDemo12Student")  
511 - .setClassComment("学生").setAuthor("芋道源码")  
512 -// .setTemplateType(CodegenTemplateTypeEnum.MASTER_INNER.getType())  
513 - .setTemplateType(CodegenTemplateTypeEnum.MASTER_ERP.getType())  
514 - .setFrontType(CodegenFrontTypeEnum.VUE3.getType());  
515 - CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())  
516 - .setId(100L)  
517 - .setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)  
518 - .setJavaType("Long").setJavaField("id").setExample("1024")  
519 - .setCreateOperation(false).setUpdateOperation(true)  
520 - .setListOperation(false)  
521 - .setListOperationResult(true);  
522 - CodegenColumnDO nameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())  
523 - .setColumnComment("名字").setNullable(false)  
524 - .setJavaType("String").setJavaField("name").setExample("芋头")  
525 - .setCreateOperation(true).setUpdateOperation(true)  
526 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())  
527 - .setListOperationResult(true)  
528 - .setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());  
529 - CodegenColumnDO descriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())  
530 - .setColumnComment("简介").setNullable(false)  
531 - .setJavaType("String").setJavaField("description").setExample("我是介绍")  
532 - .setCreateOperation(true).setUpdateOperation(true)  
533 - .setListOperation(false)  
534 - .setListOperationResult(true)  
535 - .setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());  
536 - CodegenColumnDO birthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())  
537 - .setColumnComment("出生日期").setNullable(false)  
538 - .setJavaType("LocalDateTime").setJavaField("birthday")  
539 - .setCreateOperation(true).setUpdateOperation(true)  
540 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
541 - .setListOperationResult(true)  
542 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
543 - CodegenColumnDO sexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())  
544 - .setColumnComment("性别").setNullable(false)  
545 - .setJavaType("Integer").setJavaField("sex").setExample("1")  
546 - .setCreateOperation(true).setUpdateOperation(true)  
547 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
548 - .setListOperationResult(true)  
549 - .setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())  
550 - .setDictType("system_user_sex");  
551 - CodegenColumnDO enabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())  
552 - .setColumnComment("是否有效").setNullable(false)  
553 - .setJavaType("Boolean").setJavaField("enabled").setExample("true")  
554 - .setCreateOperation(true).setUpdateOperation(true)  
555 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
556 - .setListOperationResult(true)  
557 - .setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())  
558 - .setDictType("infra_boolean_string");  
559 - CodegenColumnDO avatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())  
560 - .setColumnComment("头像").setNullable(false)  
561 - .setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")  
562 - .setCreateOperation(true).setUpdateOperation(true)  
563 - .setListOperation(false)  
564 - .setListOperationResult(true)  
565 - .setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());  
566 - CodegenColumnDO videoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())  
567 - .setColumnComment("附件").setNullable(true)  
568 - .setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")  
569 - .setCreateOperation(true).setUpdateOperation(true)  
570 - .setListOperation(false)  
571 - .setListOperationResult(true)  
572 - .setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());  
573 - CodegenColumnDO memoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())  
574 - .setColumnComment("备注").setNullable(false)  
575 - .setJavaType("String").setJavaField("memo").setExample("我是备注")  
576 - .setCreateOperation(true).setUpdateOperation(true)  
577 - .setListOperation(false)  
578 - .setListOperationResult(true)  
579 - .setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());  
580 - CodegenColumnDO createTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())  
581 - .setColumnComment("创建时间").setNullable(true)  
582 - .setJavaType("LocalDateTime").setJavaField("createTime")  
583 - .setCreateOperation(false).setUpdateOperation(false)  
584 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())  
585 - .setListOperationResult(true)  
586 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
587 - List<CodegenColumnDO> columns = Arrays.asList(idColumn, nameColumn, descriptionColumn, birthdayColumn,  
588 - sexColumn, enabledColumn, avatarColumn, videoColumn, memoColumn, createTimeColumn); 89 + public void testExecute_vue3_master_inner() {
  90 + testExecute_vue3_master(CodegenTemplateTypeEnum.MASTER_INNER, "codegen/vue3_master_inner");
  91 + }
589 92
590 - // 子表(联系人)  
591 - CodegenTableDO contactTable = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene())  
592 - .setTableName("infra_demo12_student_contact").setTableComment("学生联系人表")  
593 - .setModuleName("infra").setBusinessName("demo12").setClassName("InfraDemo12StudentContact")  
594 - .setClassComment("学生联系人").setAuthor("芋道源码") 93 + private void testExecute_vue3_master(CodegenTemplateTypeEnum templateType,
  94 + String path) {
  95 + // 准备参数
  96 + CodegenTableDO table = getTable("student")
  97 + .setFrontType(CodegenFrontTypeEnum.VUE3.getType())
  98 + .setTemplateType(templateType.getType());
  99 + List<CodegenColumnDO> columns = getColumnList("student");
  100 + // 准备参数(子表)
  101 + CodegenTableDO contactTable = getTable("contact")
595 .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) 102 .setTemplateType(CodegenTemplateTypeEnum.SUB.getType())
596 .setFrontType(CodegenFrontTypeEnum.VUE3.getType()) 103 .setFrontType(CodegenFrontTypeEnum.VUE3.getType())
597 .setSubJoinColumnId(100L).setSubJoinMany(true); 104 .setSubJoinColumnId(100L).setSubJoinMany(true);
598 - CodegenColumnDO contactIdColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())  
599 - .setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)  
600 - .setJavaType("Long").setJavaField("id").setExample("1024")  
601 - .setCreateOperation(false).setUpdateOperation(true)  
602 - .setListOperation(false)  
603 - .setListOperationResult(true);  
604 - CodegenColumnDO contactStudentIdColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name())  
605 - .setColumnComment("学生编号").setNullable(false).setPrimaryKey(false)  
606 - .setJavaType("Long").setJavaField("studentId").setExample("2048")  
607 - .setCreateOperation(true).setUpdateOperation(true)  
608 - .setListOperation(false)  
609 - .setListOperationResult(true)  
610 - .setId(100L);  
611 - CodegenColumnDO contactNameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())  
612 - .setColumnComment("名字").setNullable(false)  
613 - .setJavaType("String").setJavaField("name").setExample("芋头")  
614 - .setCreateOperation(true).setUpdateOperation(true)  
615 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())  
616 - .setListOperationResult(true)  
617 - .setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());  
618 - CodegenColumnDO contactDescriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())  
619 - .setColumnComment("简介").setNullable(false)  
620 - .setJavaType("String").setJavaField("description").setExample("我是介绍")  
621 - .setCreateOperation(true).setUpdateOperation(true)  
622 - .setListOperation(false)  
623 - .setListOperationResult(true)  
624 - .setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());  
625 - CodegenColumnDO contactBirthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())  
626 - .setColumnComment("出生日期").setNullable(false)  
627 - .setJavaType("LocalDateTime").setJavaField("birthday")  
628 - .setCreateOperation(true).setUpdateOperation(true)  
629 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
630 - .setListOperationResult(true)  
631 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
632 - CodegenColumnDO contactSexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())  
633 - .setColumnComment("性别").setNullable(false)  
634 - .setJavaType("Integer").setJavaField("sex").setExample("1")  
635 - .setCreateOperation(true).setUpdateOperation(true)  
636 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
637 - .setListOperationResult(true)  
638 - .setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())  
639 - .setDictType("system_user_sex");  
640 - CodegenColumnDO contactEnabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())  
641 - .setColumnComment("是否有效").setNullable(false)  
642 - .setJavaType("Boolean").setJavaField("enabled").setExample("true")  
643 - .setCreateOperation(true).setUpdateOperation(true)  
644 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
645 - .setListOperationResult(true)  
646 - .setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())  
647 - .setDictType("infra_boolean_string");  
648 - CodegenColumnDO contactAvatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())  
649 - .setColumnComment("头像").setNullable(false)  
650 - .setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")  
651 - .setCreateOperation(true).setUpdateOperation(true)  
652 - .setListOperation(false)  
653 - .setListOperationResult(true)  
654 - .setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());  
655 - CodegenColumnDO contactVideoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())  
656 - .setColumnComment("附件").setNullable(true)  
657 - .setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")  
658 - .setCreateOperation(true).setUpdateOperation(true)  
659 - .setListOperation(false)  
660 - .setListOperationResult(true)  
661 - .setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());  
662 - CodegenColumnDO contactMemoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())  
663 - .setColumnComment("备注").setNullable(false)  
664 - .setJavaType("String").setJavaField("memo").setExample("我是备注")  
665 - .setCreateOperation(true).setUpdateOperation(true)  
666 - .setListOperation(false)  
667 - .setListOperationResult(true)  
668 - .setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());  
669 - CodegenColumnDO contactCreateTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())  
670 - .setColumnComment("创建时间").setNullable(true)  
671 - .setJavaType("LocalDateTime").setJavaField("createTime")  
672 - .setCreateOperation(false).setUpdateOperation(false)  
673 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())  
674 - .setListOperationResult(true)  
675 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
676 - List<CodegenColumnDO> contactColumns = Arrays.asList(contactIdColumn, contactStudentIdColumn,  
677 - contactNameColumn, contactDescriptionColumn, contactBirthdayColumn,  
678 - contactSexColumn, contactEnabledColumn, contactAvatarColumn, contactVideoColumn, contactMemoColumn, contactCreateTimeColumn);  
679 -  
680 - // 子表(班主任)  
681 - CodegenTableDO teacherTable = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene())  
682 - .setTableName("infra_demo12_student_teacher").setTableComment("学生班主任表")  
683 - .setModuleName("infra").setBusinessName("demo12").setClassName("InfraDemo12StudentTeacher")  
684 - .setClassComment("学生班主任").setAuthor("芋道源码") 105 + List<CodegenColumnDO> contactColumns = getColumnList("contact");
  106 + // 准备参数(班主任)
  107 + CodegenTableDO teacherTable = getTable("teacher")
685 .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) 108 .setTemplateType(CodegenTemplateTypeEnum.SUB.getType())
686 .setFrontType(CodegenFrontTypeEnum.VUE3.getType()) 109 .setFrontType(CodegenFrontTypeEnum.VUE3.getType())
687 .setSubJoinColumnId(200L).setSubJoinMany(false); 110 .setSubJoinColumnId(200L).setSubJoinMany(false);
688 - CodegenColumnDO teacherIdColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())  
689 - .setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)  
690 - .setJavaType("Long").setJavaField("id").setExample("1024")  
691 - .setCreateOperation(false).setUpdateOperation(true)  
692 - .setListOperation(false)  
693 - .setListOperationResult(true);  
694 - CodegenColumnDO teacherStudentIdColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name())  
695 - .setColumnComment("学生编号").setNullable(false).setPrimaryKey(false)  
696 - .setJavaType("Long").setJavaField("studentId").setExample("2048")  
697 - .setCreateOperation(true).setUpdateOperation(true)  
698 - .setListOperation(false)  
699 - .setListOperationResult(true)  
700 - .setId(200L);  
701 - CodegenColumnDO teacherNameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())  
702 - .setColumnComment("名字").setNullable(false)  
703 - .setJavaType("String").setJavaField("name").setExample("芋头")  
704 - .setCreateOperation(true).setUpdateOperation(true)  
705 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())  
706 - .setListOperationResult(true)  
707 - .setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());  
708 - CodegenColumnDO teacherDescriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())  
709 - .setColumnComment("简介").setNullable(false)  
710 - .setJavaType("String").setJavaField("description").setExample("我是介绍")  
711 - .setCreateOperation(true).setUpdateOperation(true)  
712 - .setListOperation(false)  
713 - .setListOperationResult(true)  
714 - .setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());  
715 - CodegenColumnDO teacherBirthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())  
716 - .setColumnComment("出生日期").setNullable(false)  
717 - .setJavaType("LocalDateTime").setJavaField("birthday")  
718 - .setCreateOperation(true).setUpdateOperation(true)  
719 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
720 - .setListOperationResult(true)  
721 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
722 - CodegenColumnDO teacherSexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())  
723 - .setColumnComment("性别").setNullable(false)  
724 - .setJavaType("Integer").setJavaField("sex").setExample("1")  
725 - .setCreateOperation(true).setUpdateOperation(true)  
726 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
727 - .setListOperationResult(true)  
728 - .setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())  
729 - .setDictType("system_user_sex");  
730 - CodegenColumnDO teacherEnabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())  
731 - .setColumnComment("是否有效").setNullable(false)  
732 - .setJavaType("Boolean").setJavaField("enabled").setExample("true")  
733 - .setCreateOperation(true).setUpdateOperation(true)  
734 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())  
735 - .setListOperationResult(true)  
736 - .setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())  
737 - .setDictType("infra_boolean_string");  
738 - CodegenColumnDO teacherAvatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())  
739 - .setColumnComment("头像").setNullable(false)  
740 - .setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")  
741 - .setCreateOperation(true).setUpdateOperation(true)  
742 - .setListOperation(false)  
743 - .setListOperationResult(true)  
744 - .setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());  
745 - CodegenColumnDO teacherVideoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())  
746 - .setColumnComment("附件").setNullable(true)  
747 - .setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")  
748 - .setCreateOperation(true).setUpdateOperation(true)  
749 - .setListOperation(false)  
750 - .setListOperationResult(true)  
751 - .setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());  
752 - CodegenColumnDO teacherMemoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())  
753 - .setColumnComment("备注").setNullable(false)  
754 - .setJavaType("String").setJavaField("memo").setExample("我是备注")  
755 - .setCreateOperation(true).setUpdateOperation(true)  
756 - .setListOperation(false)  
757 - .setListOperationResult(true)  
758 - .setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());  
759 - CodegenColumnDO teacherCreateTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())  
760 - .setColumnComment("创建时间").setNullable(true)  
761 - .setJavaType("LocalDateTime").setJavaField("createTime")  
762 - .setCreateOperation(false).setUpdateOperation(false)  
763 - .setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())  
764 - .setListOperationResult(true)  
765 - .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());  
766 - List<CodegenColumnDO> teacherColumns = Arrays.asList(teacherIdColumn, teacherStudentIdColumn,  
767 - teacherNameColumn, teacherDescriptionColumn, teacherBirthdayColumn,  
768 - teacherSexColumn, teacherEnabledColumn, teacherAvatarColumn, teacherVideoColumn, teacherMemoColumn, teacherCreateTimeColumn); 111 + List<CodegenColumnDO> teacherColumns = getColumnList("teacher");
769 112
770 // 调用 113 // 调用
771 Map<String, String> result = codegenEngine.execute(table, columns, 114 Map<String, String> result = codegenEngine.execute(table, columns,
772 Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns)); 115 Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns));
773 -  
774 - // 构建 zip 包  
775 - writeFile(result, "/Users/yunai/test/demo12.zip");  
776 -  
777 // 断言 116 // 断言
778 - assertEquals(27, result.size()); 117 + assertResult(result, path);
  118 +// writeResult(result, "/root/ruoyi-vue-pro/yudao-module-infra/yudao-module-infra-biz/src/test/resources/" + path);
  119 +// writeFile(result, "/Users/yunai/test/demo11.zip");
  120 + }
779 121
780 - for (Map.Entry<String, String> entry : result.entrySet()) {  
781 - System.out.println(entry.getKey());  
782 - System.out.println(entry.getValue());  
783 - System.out.println("");  
784 - System.out.println("");  
785 - System.out.println("");  
786 - } 122 + private static CodegenTableDO getTable(String name) {
  123 + String content = ResourceUtil.readUtf8Str("codegen/table/" + name + ".json");
  124 + return JsonUtils.parseObject(content, "table", CodegenTableDO.class);
787 } 125 }
788 126
789 - private void assertPathContentEquals(String path, Map<String, String> result, String key) {  
790 - String pathContent = ResourceUtil.readUtf8Str("codegen/" + path);  
791 - String valueContent = result.get(key);  
792 - assertEquals(pathContent, valueContent); 127 + private static List<CodegenColumnDO> getColumnList(String name) {
  128 + String content = ResourceUtil.readUtf8Str("codegen/table/" + name + ".json");
  129 + List<CodegenColumnDO> list = JsonUtils.parseArray(content, "columns", CodegenColumnDO.class);
  130 + list.forEach(column -> {
  131 + if (column.getNullable() == null) {
  132 + column.setNullable(false);
  133 + }
  134 + if (column.getCreateOperation() == null) {
  135 + column.setCreateOperation(false);
  136 + }
  137 + if (column.getUpdateOperation() == null) {
  138 + column.setUpdateOperation(false);
  139 + }
  140 + if (column.getListOperation() == null) {
  141 + column.setListOperation(false);
  142 + }
  143 + if (column.getListOperationResult() == null) {
  144 + column.setListOperationResult(false);
  145 + }
  146 + });
  147 + return list;
793 } 148 }
794 149
  150 + @SuppressWarnings("rawtypes")
  151 + private static void assertResult(Map<String, String> result, String path) {
  152 + String assertContent = ResourceUtil.readUtf8Str(path + "/assert.json");
  153 + List<HashMap> asserts = JsonUtils.parseArray(assertContent, HashMap.class);
  154 + assertEquals(asserts.size(), result.size());
  155 + // 校验每个文件
  156 + asserts.forEach(assertMap -> {
  157 + String contentPath = (String) assertMap.get("contentPath");
  158 + String filePath = (String) assertMap.get("filePath");
  159 + String content = ResourceUtil.readUtf8Str(path + "/" + contentPath);
  160 + assertEquals(content, result.get(filePath), filePath + ":不匹配");
  161 + });
  162 + }
  163 +
  164 + // ==================== 调试专用 ====================
  165 +
795 /** 166 /**
796 - * 将生成的代码,写入到文件  
797 - *  
798 - * 用途:方便本地调试 167 + * 【调试使用】将生成的代码,写入到文件
799 * 168 *
800 * @param result 生成的代码 169 * @param result 生成的代码
801 * @param path 写入文件的路径 170 * @param path 写入文件的路径
@@ -810,4 +179,25 @@ public class CodegenEngineTest extends BaseMockitoUnitTest { @@ -810,4 +179,25 @@ public class CodegenEngineTest extends BaseMockitoUnitTest {
810 FileUtil.writeBytes(outputStream.toByteArray(), path); 179 FileUtil.writeBytes(outputStream.toByteArray(), path);
811 } 180 }
812 181
  182 + /**
  183 + * 【调试使用】将生成的结果,写入到文件
  184 + *
  185 + * @param result 生成的代码
  186 + * @param basePath 写入文件的路径(绝对路径)
  187 + */
  188 + private void writeResult(Map<String, String> result, String basePath) {
  189 + // 写入文件内容
  190 + List<Map<String, String>> asserts = new ArrayList<>();
  191 + result.forEach((filePath, fileContent) -> {
  192 + String lastFilePath = StrUtil.subAfter(filePath, '/', true);
  193 + String contentPath = StrUtil.subAfter(lastFilePath, '.', true)
  194 + + '/' + StrUtil.subBefore(lastFilePath, '.', true);
  195 + asserts.add(MapUtil.<String, String>builder().put("filePath", filePath)
  196 + .put("contentPath", contentPath).build());
  197 + FileUtil.writeUtf8String(fileContent, basePath + "/" + contentPath);
  198 + });
  199 + // 写入 assert.json 文件
  200 + FileUtil.writeUtf8String(JsonUtils.toJsonPrettyString(asserts), basePath +"/assert.json");
  201 + }
  202 +
813 } 203 }
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/table/category.json 0 → 100644
  1 +{
  2 + "table": {
  3 + "id": 10,
  4 + "scene" : 1,
  5 + "parentMenuId" : 888,
  6 + "tableName" : "infra_category",
  7 + "tableComment" : "分类表",
  8 + "moduleName" : "infra",
  9 + "businessName" : "demo",
  10 + "className" : "InfraCategory",
  11 + "classComment" : "分类",
  12 + "author" : "芋道源码",
  13 + "treeParentColumnId" : 22,
  14 + "treeNameColumnId" : 11
  15 + },
  16 + "columns": [ {
  17 + "columnName" : "id",
  18 + "dataType" : "BIGINT",
  19 + "columnComment" : "编号",
  20 + "primaryKey" : true,
  21 + "autoIncrement" : true,
  22 + "javaType" : "Long",
  23 + "javaField" : "id",
  24 + "example" : "1024",
  25 + "updateOperation" : true,
  26 + "listOperationResult" : true
  27 + }, {
  28 + "id" : 11,
  29 + "columnName" : "name",
  30 + "dataType" : "VARCHAR",
  31 + "columnComment" : "名字",
  32 + "javaType" : "String",
  33 + "javaField" : "name",
  34 + "example" : "芋头",
  35 + "createOperation" : true,
  36 + "updateOperation" : true,
  37 + "listOperation" : true,
  38 + "listOperationCondition" : "LIKE",
  39 + "listOperationResult" : true,
  40 + "htmlType" : "input"
  41 + }, {
  42 + "id" : 22,
  43 + "columnName" : "description",
  44 + "dataType" : "VARCHAR",
  45 + "columnComment" : "父编号",
  46 + "javaType" : "Long",
  47 + "javaField" : "parentId",
  48 + "example" : "2048",
  49 + "createOperation" : true,
  50 + "updateOperation" : true,
  51 + "listOperationResult" : true
  52 + } ]
  53 +}
0 \ No newline at end of file 54 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/table/contact.json
  1 +{
  2 + "table": {
  3 + "scene" : 1,
  4 + "tableName" : "infra_student_contact",
  5 + "tableComment" : "学生联系人表",
  6 + "moduleName" : "infra",
  7 + "businessName" : "demo",
  8 + "className" : "InfraStudentContact",
  9 + "classComment" : "学生联系人",
  10 + "author" : "芋道源码"
  11 + },
  12 + "columns": [ {
  13 + "columnName" : "id",
  14 + "dataType" : "BIGINT",
  15 + "columnComment" : "编号",
  16 + "primaryKey" : true,
  17 + "autoIncrement" : true,
  18 + "javaType" : "Long",
  19 + "javaField" : "id",
  20 + "example" : "1024",
  21 + "updateOperation" : true,
  22 + "listOperationResult" : true
  23 + }, {
  24 + "id" : 100,
  25 + "columnName" : "student_id",
  26 + "dataType" : "BIGINT",
  27 + "columnComment" : "学生编号",
  28 + "javaType" : "Long",
  29 + "javaField" : "studentId",
  30 + "example" : "2048",
  31 + "createOperation" : true,
  32 + "updateOperation" : true,
  33 + "listOperationResult" : true
  34 + }, {
  35 + "columnName" : "name",
  36 + "dataType" : "VARCHAR",
  37 + "columnComment" : "名字",
  38 + "javaType" : "String",
  39 + "javaField" : "name",
  40 + "example" : "芋头",
  41 + "createOperation" : true,
  42 + "updateOperation" : true,
  43 + "listOperation" : true,
  44 + "listOperationCondition" : "LIKE",
  45 + "listOperationResult" : true,
  46 + "htmlType" : "input"
  47 + }, {
  48 + "columnName" : "description",
  49 + "dataType" : "VARCHAR",
  50 + "columnComment" : "简介",
  51 + "javaType" : "String",
  52 + "javaField" : "description",
  53 + "example" : "我是介绍",
  54 + "createOperation" : true,
  55 + "updateOperation" : true,
  56 + "listOperationResult" : true,
  57 + "htmlType" : "textarea"
  58 + }, {
  59 + "columnName" : "birthday",
  60 + "dataType" : "DATE",
  61 + "columnComment" : "出生日期",
  62 + "javaType" : "LocalDateTime",
  63 + "javaField" : "birthday",
  64 + "createOperation" : true,
  65 + "updateOperation" : true,
  66 + "listOperation" : true,
  67 + "listOperationCondition" : "=",
  68 + "listOperationResult" : true,
  69 + "htmlType" : "datetime"
  70 + }, {
  71 + "columnName" : "sex",
  72 + "dataType" : "INTEGER",
  73 + "columnComment" : "性别",
  74 + "javaType" : "Integer",
  75 + "javaField" : "sex",
  76 + "dictType" : "system_user_sex",
  77 + "example" : "1",
  78 + "createOperation" : true,
  79 + "updateOperation" : true,
  80 + "listOperation" : true,
  81 + "listOperationCondition" : "=",
  82 + "listOperationResult" : true,
  83 + "htmlType" : "select"
  84 + }, {
  85 + "columnName" : "enabled",
  86 + "dataType" : "BOOLEAN",
  87 + "columnComment" : "是否有效",
  88 + "javaType" : "Boolean",
  89 + "javaField" : "enabled",
  90 + "dictType" : "infra_boolean_string",
  91 + "example" : "true",
  92 + "createOperation" : true,
  93 + "updateOperation" : true,
  94 + "listOperation" : true,
  95 + "listOperationCondition" : "=",
  96 + "listOperationResult" : true,
  97 + "htmlType" : "radio"
  98 + }, {
  99 + "columnName" : "avatar",
  100 + "dataType" : "VARCHAR",
  101 + "columnComment" : "头像",
  102 + "javaType" : "String",
  103 + "javaField" : "avatar",
  104 + "example" : "https://www.iocoder.cn/1.png",
  105 + "createOperation" : true,
  106 + "updateOperation" : true,
  107 + "listOperationResult" : true,
  108 + "htmlType" : "imageUpload"
  109 + }, {
  110 + "columnName" : "video",
  111 + "dataType" : "VARCHAR",
  112 + "columnComment" : "附件",
  113 + "nullable" : true,
  114 + "javaType" : "String",
  115 + "javaField" : "video",
  116 + "example" : "https://www.iocoder.cn/1.mp4",
  117 + "createOperation" : true,
  118 + "updateOperation" : true,
  119 + "listOperationResult" : true,
  120 + "htmlType" : "fileUpload"
  121 + }, {
  122 + "columnName" : "memo",
  123 + "dataType" : "VARCHAR",
  124 + "columnComment" : "备注",
  125 + "javaType" : "String",
  126 + "javaField" : "memo",
  127 + "example" : "我是备注",
  128 + "createOperation" : true,
  129 + "updateOperation" : true,
  130 + "listOperationResult" : true,
  131 + "htmlType" : "editor"
  132 + }, {
  133 + "columnName" : "create_time",
  134 + "dataType" : "DATE",
  135 + "columnComment" : "创建时间",
  136 + "nullable" : true,
  137 + "javaType" : "LocalDateTime",
  138 + "javaField" : "createTime",
  139 + "listOperation" : true,
  140 + "listOperationCondition" : "BETWEEN",
  141 + "listOperationResult" : true,
  142 + "htmlType" : "datetime"
  143 + } ]
  144 +}
0 \ No newline at end of file 145 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/table/extension.json deleted
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/table/student.json
1 { 1 {
2 "table": { 2 "table": {
3 - 3 + "id": 1,
  4 + "scene" : 1,
  5 + "parentMenuId" : 888,
  6 + "tableName" : "infra_student",
  7 + "tableComment" : "学生表",
  8 + "moduleName" : "infra",
  9 + "businessName" : "demo",
  10 + "className" : "InfraStudent",
  11 + "classComment" : "学生",
  12 + "author" : "芋道源码"
4 }, 13 },
5 - "columns": [{  
6 -  
7 - }] 14 + "columns": [ {
  15 + "id" : 100,
  16 + "columnName" : "id",
  17 + "dataType" : "BIGINT",
  18 + "columnComment" : "编号",
  19 + "primaryKey" : true,
  20 + "autoIncrement" : true,
  21 + "javaType" : "Long",
  22 + "javaField" : "id",
  23 + "example" : "1024",
  24 + "updateOperation" : true,
  25 + "listOperationResult" : true
  26 + }, {
  27 + "columnName" : "name",
  28 + "dataType" : "VARCHAR",
  29 + "columnComment" : "名字",
  30 + "javaType" : "String",
  31 + "javaField" : "name",
  32 + "example" : "芋头",
  33 + "createOperation" : true,
  34 + "updateOperation" : true,
  35 + "listOperation" : true,
  36 + "listOperationCondition" : "LIKE",
  37 + "listOperationResult" : true,
  38 + "htmlType" : "input"
  39 + }, {
  40 + "columnName" : "description",
  41 + "dataType" : "VARCHAR",
  42 + "columnComment" : "简介",
  43 + "javaType" : "String",
  44 + "javaField" : "description",
  45 + "example" : "我是介绍",
  46 + "createOperation" : true,
  47 + "updateOperation" : true,
  48 + "listOperationResult" : true,
  49 + "htmlType" : "textarea"
  50 + }, {
  51 + "columnName" : "birthday",
  52 + "dataType" : "DATE",
  53 + "columnComment" : "出生日期",
  54 + "javaType" : "LocalDateTime",
  55 + "javaField" : "birthday",
  56 + "createOperation" : true,
  57 + "updateOperation" : true,
  58 + "listOperation" : true,
  59 + "listOperationCondition" : "=",
  60 + "listOperationResult" : true,
  61 + "htmlType" : "datetime"
  62 + }, {
  63 + "columnName" : "sex",
  64 + "dataType" : "INTEGER",
  65 + "columnComment" : "性别",
  66 + "javaType" : "Integer",
  67 + "javaField" : "sex",
  68 + "dictType" : "system_user_sex",
  69 + "example" : "1",
  70 + "createOperation" : true,
  71 + "updateOperation" : true,
  72 + "listOperation" : true,
  73 + "listOperationCondition" : "=",
  74 + "listOperationResult" : true,
  75 + "htmlType" : "select"
  76 + }, {
  77 + "columnName" : "enabled",
  78 + "dataType" : "BOOLEAN",
  79 + "columnComment" : "是否有效",
  80 + "javaType" : "Boolean",
  81 + "javaField" : "enabled",
  82 + "dictType" : "infra_boolean_string",
  83 + "example" : "true",
  84 + "createOperation" : true,
  85 + "updateOperation" : true,
  86 + "listOperation" : true,
  87 + "listOperationCondition" : "=",
  88 + "listOperationResult" : true,
  89 + "htmlType" : "radio"
  90 + }, {
  91 + "columnName" : "avatar",
  92 + "dataType" : "VARCHAR",
  93 + "columnComment" : "头像",
  94 + "javaType" : "String",
  95 + "javaField" : "avatar",
  96 + "example" : "https://www.iocoder.cn/1.png",
  97 + "createOperation" : true,
  98 + "updateOperation" : true,
  99 + "listOperationResult" : true,
  100 + "htmlType" : "imageUpload"
  101 + }, {
  102 + "columnName" : "video",
  103 + "dataType" : "VARCHAR",
  104 + "columnComment" : "附件",
  105 + "javaType" : "String",
  106 + "javaField" : "video",
  107 + "example" : "https://www.iocoder.cn/1.mp4",
  108 + "createOperation" : true,
  109 + "updateOperation" : true,
  110 + "listOperationResult" : true,
  111 + "htmlType" : "fileUpload"
  112 + }, {
  113 + "columnName" : "memo",
  114 + "dataType" : "VARCHAR",
  115 + "columnComment" : "备注",
  116 + "javaType" : "String",
  117 + "javaField" : "memo",
  118 + "example" : "我是备注",
  119 + "createOperation" : true,
  120 + "updateOperation" : true,
  121 + "listOperationResult" : true,
  122 + "htmlType" : "editor"
  123 + }, {
  124 + "columnName" : "create_time",
  125 + "dataType" : "DATE",
  126 + "columnComment" : "创建时间",
  127 + "nullable" : true,
  128 + "javaType" : "LocalDateTime",
  129 + "javaField" : "createTime",
  130 + "listOperation" : true,
  131 + "listOperationCondition" : "BETWEEN",
  132 + "listOperationResult" : true,
  133 + "htmlType" : "datetime"
  134 + } ]
8 } 135 }
9 \ No newline at end of file 136 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/table/teacher.json 0 → 100644
  1 +{
  2 + "table": {
  3 + "scene" : 1,
  4 + "tableName" : "infra_student_teacher",
  5 + "tableComment" : "学生班主任表",
  6 + "moduleName" : "infra",
  7 + "businessName" : "demo",
  8 + "className" : "InfraStudentTeacher",
  9 + "classComment" : "学生班主任",
  10 + "author" : "芋道源码"
  11 + },
  12 + "columns": [ {
  13 + "columnName" : "id",
  14 + "dataType" : "BIGINT",
  15 + "columnComment" : "编号",
  16 + "primaryKey" : true,
  17 + "autoIncrement" : true,
  18 + "javaType" : "Long",
  19 + "javaField" : "id",
  20 + "example" : "1024",
  21 + "updateOperation" : true,
  22 + "listOperationResult" : true
  23 + }, {
  24 + "id" : 200,
  25 + "columnName" : "student_id",
  26 + "dataType" : "BIGINT",
  27 + "columnComment" : "学生编号",
  28 + "javaType" : "Long",
  29 + "javaField" : "studentId",
  30 + "example" : "2048",
  31 + "createOperation" : true,
  32 + "updateOperation" : true,
  33 + "listOperationResult" : true
  34 + }, {
  35 + "columnName" : "name",
  36 + "dataType" : "VARCHAR",
  37 + "columnComment" : "名字",
  38 + "javaType" : "String",
  39 + "javaField" : "name",
  40 + "example" : "芋头",
  41 + "createOperation" : true,
  42 + "updateOperation" : true,
  43 + "listOperation" : true,
  44 + "listOperationCondition" : "LIKE",
  45 + "listOperationResult" : true,
  46 + "htmlType" : "input"
  47 + }, {
  48 + "columnName" : "description",
  49 + "dataType" : "VARCHAR",
  50 + "columnComment" : "简介",
  51 + "javaType" : "String",
  52 + "javaField" : "description",
  53 + "example" : "我是介绍",
  54 + "createOperation" : true,
  55 + "updateOperation" : true,
  56 + "listOperationResult" : true,
  57 + "htmlType" : "textarea"
  58 + }, {
  59 + "columnName" : "birthday",
  60 + "dataType" : "DATE",
  61 + "columnComment" : "出生日期",
  62 + "javaType" : "LocalDateTime",
  63 + "javaField" : "birthday",
  64 + "createOperation" : true,
  65 + "updateOperation" : true,
  66 + "listOperation" : true,
  67 + "listOperationCondition" : "=",
  68 + "listOperationResult" : true,
  69 + "htmlType" : "datetime"
  70 + }, {
  71 + "columnName" : "sex",
  72 + "dataType" : "INTEGER",
  73 + "columnComment" : "性别",
  74 + "javaType" : "Integer",
  75 + "javaField" : "sex",
  76 + "dictType" : "system_user_sex",
  77 + "example" : "1",
  78 + "createOperation" : true,
  79 + "updateOperation" : true,
  80 + "listOperation" : true,
  81 + "listOperationCondition" : "=",
  82 + "listOperationResult" : true,
  83 + "htmlType" : "select"
  84 + }, {
  85 + "columnName" : "enabled",
  86 + "dataType" : "BOOLEAN",
  87 + "columnComment" : "是否有效",
  88 + "javaType" : "Boolean",
  89 + "javaField" : "enabled",
  90 + "dictType" : "infra_boolean_string",
  91 + "example" : "true",
  92 + "createOperation" : true,
  93 + "updateOperation" : true,
  94 + "listOperation" : true,
  95 + "listOperationCondition" : "=",
  96 + "listOperationResult" : true,
  97 + "htmlType" : "radio"
  98 + }, {
  99 + "columnName" : "avatar",
  100 + "dataType" : "VARCHAR",
  101 + "columnComment" : "头像",
  102 + "javaType" : "String",
  103 + "javaField" : "avatar",
  104 + "example" : "https://www.iocoder.cn/1.png",
  105 + "createOperation" : true,
  106 + "updateOperation" : true,
  107 + "listOperationResult" : true,
  108 + "htmlType" : "imageUpload"
  109 + }, {
  110 + "columnName" : "video",
  111 + "dataType" : "VARCHAR",
  112 + "columnComment" : "附件",
  113 + "nullable" : true,
  114 + "javaType" : "String",
  115 + "javaField" : "video",
  116 + "example" : "https://www.iocoder.cn/1.mp4",
  117 + "createOperation" : true,
  118 + "updateOperation" : true,
  119 + "listOperationResult" : true,
  120 + "htmlType" : "fileUpload"
  121 + }, {
  122 + "columnName" : "memo",
  123 + "dataType" : "VARCHAR",
  124 + "columnComment" : "备注",
  125 + "javaType" : "String",
  126 + "javaField" : "memo",
  127 + "example" : "我是备注",
  128 + "createOperation" : true,
  129 + "updateOperation" : true,
  130 + "listOperationResult" : true,
  131 + "htmlType" : "editor"
  132 + }, {
  133 + "columnName" : "create_time",
  134 + "dataType" : "DATE",
  135 + "columnComment" : "创建时间",
  136 + "nullable" : true,
  137 + "javaType" : "LocalDateTime",
  138 + "javaField" : "createTime",
  139 + "listOperation" : true,
  140 + "listOperationCondition" : "BETWEEN",
  141 + "listOperationResult" : true,
  142 + "htmlType" : "datetime"
  143 + } ]
  144 +}
0 \ No newline at end of file 145 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/ErrorCodeConstants deleted
1 -// TODO 待办:请将下面的错误码复制到 yudao-module-system-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!!  
2 -// ========== 用户 TODO 补充编号 ==========  
3 -ErrorCode USER_NOT_EXISTS = new ErrorCode(TODO 补充编号, "用户不存在");  
4 \ No newline at end of file 0 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserBaseVO deleted
1 -package cn.iocoder.yudao.module.system.controller.admin.user.vo;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.*;  
5 -import java.util.*;  
6 -import java.time.LocalDateTime;  
7 -import java.time.LocalDateTime;  
8 -import javax.validation.constraints.*;  
9 -import org.springframework.format.annotation.DateTimeFormat;  
10 -  
11 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;  
12 -  
13 -/**  
14 - * 用户 Base VO,提供给添加、修改、详细的子 VO 使用  
15 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成  
16 - */  
17 -@Data  
18 -public class SystemUserBaseVO {  
19 -  
20 - @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")  
21 - @NotEmpty(message = "名字不能为空")  
22 - private String name;  
23 -  
24 - @Schema(description = "头像", example = "https://www.iocoder.cn/1.png")  
25 - private String avatar;  
26 -  
27 - @Schema(description = "视频", example = "https://www.iocoder.cn/1.mp4")  
28 - private String video;  
29 -  
30 - @Schema(description = "个人简介", example = "我是介绍")  
31 - private String description;  
32 -  
33 - @Schema(description = "性别 1", example = "男")  
34 - private String sex1;  
35 -  
36 - @Schema(description = "性别 2", example = "1")  
37 - private Integer sex2;  
38 -  
39 - @Schema(description = "性别 3", example = "true")  
40 - private Boolean sex3;  
41 -  
42 - @Schema(description = "出生日期")  
43 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
44 - private LocalDateTime birthday;  
45 -  
46 - @Schema(description = "备注", example = "我是备注")  
47 - private String memo;  
48 -  
49 - @Schema(description = "创建时间")  
50 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
51 - private LocalDateTime createTime;  
52 -  
53 -}  
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserController deleted
1 -package cn.iocoder.yudao.module.system.controller.admin.user;  
2 -  
3 -import org.springframework.web.bind.annotation.*;  
4 -import javax.annotation.Resource;  
5 -import org.springframework.validation.annotation.Validated;  
6 -import org.springframework.security.access.prepost.PreAuthorize;  
7 -import io.swagger.v3.oas.annotations.tags.Tag;  
8 -import io.swagger.v3.oas.annotations.Parameter;  
9 -import io.swagger.v3.oas.annotations.Operation;  
10 -  
11 -import javax.validation.constraints.*;  
12 -import javax.validation.*;  
13 -import javax.servlet.http.*;  
14 -import java.util.*;  
15 -import java.io.IOException;  
16 -  
17 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
18 -import cn.iocoder.yudao.framework.common.pojo.CommonResult;  
19 -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;  
20 -  
21 -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;  
22 -  
23 -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;  
24 -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;  
25 -  
26 -import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;  
27 -import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;  
28 -import cn.iocoder.yudao.module.system.convert.user.SystemUserConvert;  
29 -import cn.iocoder.yudao.module.system.service.user.SystemUserService;  
30 -  
31 -@Tag(name = "管理后台 - 用户")  
32 -@RestController  
33 -@RequestMapping("/system/user")  
34 -@Validated  
35 -public class SystemUserController {  
36 -  
37 - @Resource  
38 - private SystemUserService userService;  
39 -  
40 - @PostMapping("/create")  
41 - @Operation(summary = "创建用户")  
42 - @PreAuthorize("@ss.hasPermission('system:user:create')")  
43 - public CommonResult<Long> createUser(@Valid @RequestBody SystemUserCreateReqVO createReqVO) {  
44 - return success(userService.createUser(createReqVO));  
45 - }  
46 -  
47 - @PutMapping("/update")  
48 - @Operation(summary = "更新用户")  
49 - @PreAuthorize("@ss.hasPermission('system:user:update')")  
50 - public CommonResult<Boolean> updateUser(@Valid @RequestBody SystemUserUpdateReqVO updateReqVO) {  
51 - userService.updateUser(updateReqVO);  
52 - return success(true);  
53 - }  
54 -  
55 - @DeleteMapping("/delete")  
56 - @Operation(summary = "删除用户")  
57 - @Parameter(name = "id", description = "编号", required = true)  
58 - @PreAuthorize("@ss.hasPermission('system:user:delete')")  
59 - public CommonResult<Boolean> deleteUser(@RequestParam("id") Long id) {  
60 - userService.deleteUser(id);  
61 - return success(true);  
62 - }  
63 -  
64 - @GetMapping("/get")  
65 - @Operation(summary = "获得用户")  
66 - @Parameter(name = "id", description = "编号", required = true, example = "1024")  
67 - @PreAuthorize("@ss.hasPermission('system:user:query')")  
68 - public CommonResult<SystemUserRespVO> getUser(@RequestParam("id") Long id) {  
69 - SystemUserDO user = userService.getUser(id);  
70 - return success(SystemUserConvert.INSTANCE.convert(user));  
71 - }  
72 -  
73 - @GetMapping("/list")  
74 - @Operation(summary = "获得用户列表")  
75 - @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")  
76 - @PreAuthorize("@ss.hasPermission('system:user:query')")  
77 - public CommonResult<List<SystemUserRespVO>> getUserList(@RequestParam("ids") Collection<Long> ids) {  
78 - List<SystemUserDO> list = userService.getUserList(ids);  
79 - return success(SystemUserConvert.INSTANCE.convertList(list));  
80 - }  
81 -  
82 - @GetMapping("/page")  
83 - @Operation(summary = "获得用户分页")  
84 - @PreAuthorize("@ss.hasPermission('system:user:query')")  
85 - public CommonResult<PageResult<SystemUserRespVO>> getUserPage(@Valid SystemUserPageReqVO pageVO) {  
86 - PageResult<SystemUserDO> pageResult = userService.getUserPage(pageVO);  
87 - return success(SystemUserConvert.INSTANCE.convertPage(pageResult));  
88 - }  
89 -  
90 - @GetMapping("/export-excel")  
91 - @Operation(summary = "导出用户 Excel")  
92 - @PreAuthorize("@ss.hasPermission('system:user:export')")  
93 - @OperateLog(type = EXPORT)  
94 - public void exportUserExcel(@Valid SystemUserExportReqVO exportReqVO,  
95 - HttpServletResponse response) throws IOException {  
96 - List<SystemUserDO> list = userService.getUserList(exportReqVO);  
97 - // 导出 Excel  
98 - List<SystemUserExcelVO> datas = SystemUserConvert.INSTANCE.convertList02(list);  
99 - ExcelUtils.write(response, "用户.xls", "数据", SystemUserExcelVO.class, datas);  
100 - }  
101 -  
102 -}  
103 \ No newline at end of file 0 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserConvert deleted
1 -package cn.iocoder.yudao.module.system.convert.user;  
2 -  
3 -import java.util.*;  
4 -  
5 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
6 -  
7 -import org.mapstruct.Mapper;  
8 -import org.mapstruct.factory.Mappers;  
9 -import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;  
10 -import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;  
11 -  
12 -/**  
13 - * 用户 Convert  
14 - *  
15 - * @author 芋道源码  
16 - */  
17 -@Mapper  
18 -public interface SystemUserConvert {  
19 -  
20 - SystemUserConvert INSTANCE = Mappers.getMapper(SystemUserConvert.class);  
21 -  
22 - SystemUserDO convert(SystemUserCreateReqVO bean);  
23 -  
24 - SystemUserDO convert(SystemUserUpdateReqVO bean);  
25 -  
26 - SystemUserRespVO convert(SystemUserDO bean);  
27 -  
28 - List<SystemUserRespVO> convertList(List<SystemUserDO> list);  
29 -  
30 - PageResult<SystemUserRespVO> convertPage(PageResult<SystemUserDO> page);  
31 -  
32 - List<SystemUserExcelVO> convertList02(List<SystemUserDO> list);  
33 -  
34 -}  
35 \ No newline at end of file 0 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserCreateReqVO deleted
1 -package cn.iocoder.yudao.module.system.controller.admin.user.vo;  
2 -  
3 -import lombok.*;  
4 -import java.util.*;  
5 -import io.swagger.v3.oas.annotations.media.Schema;  
6 -import javax.validation.constraints.*;  
7 -  
8 -@Schema(description = "管理后台 - 用户创建 Request VO")  
9 -@Data  
10 -@EqualsAndHashCode(callSuper = true)  
11 -@ToString(callSuper = true)  
12 -public class SystemUserCreateReqVO extends SystemUserBaseVO {  
13 -  
14 -}  
15 \ No newline at end of file 0 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserExcelVO deleted
1 -package cn.iocoder.yudao.module.system.controller.admin.user.vo;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.*;  
5 -import java.util.*;  
6 -import java.time.LocalDateTime;  
7 -import java.time.LocalDateTime;  
8 -  
9 -import com.alibaba.excel.annotation.ExcelProperty;  
10 -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;  
11 -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;  
12 -  
13 -  
14 -/**  
15 - * 用户 Excel VO  
16 - *  
17 - * @author 芋道源码  
18 - */  
19 -@Data  
20 -public class SystemUserExcelVO {  
21 -  
22 - @ExcelProperty("编号")  
23 - private Long id;  
24 -  
25 - @ExcelProperty("名字")  
26 - private String name;  
27 -  
28 - @ExcelProperty("头像")  
29 - private String avatar;  
30 -  
31 - @ExcelProperty("视频")  
32 - private String video;  
33 -  
34 - @ExcelProperty("个人简介")  
35 - private String description;  
36 -  
37 - @ExcelProperty(value = "性别 1", converter = DictConvert.class)  
38 - @DictFormat("system_sex1") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中  
39 - private String sex1;  
40 -  
41 - @ExcelProperty(value = "性别 2", converter = DictConvert.class)  
42 - @DictFormat("system_sex2") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中  
43 - private Integer sex2;  
44 -  
45 - @ExcelProperty(value = "性别 3", converter = DictConvert.class)  
46 - @DictFormat("system_sex3") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中  
47 - private Boolean sex3;  
48 -  
49 - @ExcelProperty("出生日期")  
50 - private LocalDateTime birthday;  
51 -  
52 - @ExcelProperty("备注")  
53 - private String memo;  
54 -  
55 - @ExcelProperty("创建时间")  
56 - private LocalDateTime createTime;  
57 -  
58 -}  
59 \ No newline at end of file 0 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserMapper deleted
1 -package cn.iocoder.yudao.module.system.dal.mysql.user;  
2 -  
3 -import java.util.*;  
4 -  
5 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
6 -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;  
7 -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;  
8 -import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;  
9 -import org.apache.ibatis.annotations.Mapper;  
10 -import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;  
11 -  
12 -/**  
13 - * 用户 Mapper  
14 - *  
15 - * @author 芋道源码  
16 - */  
17 -@Mapper  
18 -public interface SystemUserMapper extends BaseMapperX<SystemUserDO> {  
19 -  
20 - default PageResult<SystemUserDO> selectPage(SystemUserPageReqVO reqVO) {  
21 - return selectPage(reqVO, new LambdaQueryWrapperX<SystemUserDO>()  
22 - .likeIfPresent(SystemUserDO::getName, reqVO.getName())  
23 - .eqIfPresent(SystemUserDO::getSex1, reqVO.getSex1())  
24 - .eqIfPresent(SystemUserDO::getSex2, reqVO.getSex2())  
25 - .eqIfPresent(SystemUserDO::getBirthday, reqVO.getBirthday())  
26 - .betweenIfPresent(SystemUserDO::getCreateTime, reqVO.getCreateTime())  
27 - .orderByDesc(SystemUserDO::getId));  
28 - }  
29 -  
30 - default List<SystemUserDO> selectList(SystemUserExportReqVO reqVO) {  
31 - return selectList(new LambdaQueryWrapperX<SystemUserDO>()  
32 - .likeIfPresent(SystemUserDO::getName, reqVO.getName())  
33 - .eqIfPresent(SystemUserDO::getSex1, reqVO.getSex1())  
34 - .eqIfPresent(SystemUserDO::getSex2, reqVO.getSex2())  
35 - .eqIfPresent(SystemUserDO::getBirthday, reqVO.getBirthday())  
36 - .betweenIfPresent(SystemUserDO::getCreateTime, reqVO.getCreateTime())  
37 - .orderByDesc(SystemUserDO::getId));  
38 - }  
39 -  
40 -}  
41 \ No newline at end of file 0 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserRespVO deleted
1 -package cn.iocoder.yudao.module.system.controller.admin.user.vo;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.*;  
5 -import java.time.LocalDateTime;  
6 -  
7 -@Schema(description = "管理后台 - 用户 Response VO")  
8 -@Data  
9 -@EqualsAndHashCode(callSuper = true)  
10 -@ToString(callSuper = true)  
11 -public class SystemUserRespVO extends SystemUserBaseVO {  
12 -  
13 - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")  
14 - private Long id;  
15 -  
16 -}  
17 \ No newline at end of file 0 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserServiceImpl deleted
1 -package cn.iocoder.yudao.module.system.service.user;  
2 -  
3 -import org.springframework.stereotype.Service;  
4 -import javax.annotation.Resource;  
5 -import org.springframework.validation.annotation.Validated;  
6 -  
7 -import java.util.*;  
8 -import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;  
9 -import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;  
10 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
11 -  
12 -import cn.iocoder.yudao.module.system.convert.user.SystemUserConvert;  
13 -import cn.iocoder.yudao.module.system.dal.mysql.user.SystemUserMapper;  
14 -  
15 -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;  
16 -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;  
17 -  
18 -import cn.hutool.core.collection.CollUtil;  
19 -import cn.hutool.core.collection.ListUtil;  
20 -  
21 -/**  
22 - * 用户 Service 实现类  
23 - *  
24 - * @author 芋道源码  
25 - */  
26 -@Service  
27 -@Validated  
28 -public class SystemUserServiceImpl implements SystemUserService {  
29 -  
30 - @Resource  
31 - private SystemUserMapper userMapper;  
32 -  
33 - @Override  
34 - public Long createUser(SystemUserCreateReqVO createReqVO) {  
35 - // 插入  
36 - SystemUserDO user = SystemUserConvert.INSTANCE.convert(createReqVO);  
37 - userMapper.insert(user);  
38 - // 返回  
39 - return user.getId();  
40 - }  
41 -  
42 - @Override  
43 - public void updateUser(SystemUserUpdateReqVO updateReqVO) {  
44 - // 校验存在  
45 - validateUserExists(updateReqVO.getId());  
46 - // 更新  
47 - SystemUserDO updateObj = SystemUserConvert.INSTANCE.convert(updateReqVO);  
48 - userMapper.updateById(updateObj);  
49 - }  
50 -  
51 - @Override  
52 - public void deleteUser(Long id) {  
53 - // 校验存在  
54 - validateUserExists(id);  
55 - // 删除  
56 - userMapper.deleteById(id);  
57 - }  
58 -  
59 - private void validateUserExists(Long id) {  
60 - if (userMapper.selectById(id) == null) {  
61 - throw exception(USER_NOT_EXISTS);  
62 - }  
63 - }  
64 -  
65 - @Override  
66 - public SystemUserDO getUser(Long id) {  
67 - return userMapper.selectById(id);  
68 - }  
69 -  
70 - @Override  
71 - public List<SystemUserDO> getUserList(Collection<Long> ids) {  
72 - if (CollUtil.isEmpty(ids)) {  
73 - return ListUtil.empty();  
74 - }  
75 - return userMapper.selectBatchIds(ids);  
76 - }  
77 -  
78 - @Override  
79 - public PageResult<SystemUserDO> getUserPage(SystemUserPageReqVO pageReqVO) {  
80 - return userMapper.selectPage(pageReqVO);  
81 - }  
82 -  
83 - @Override  
84 - public List<SystemUserDO> getUserList(SystemUserExportReqVO exportReqVO) {  
85 - return userMapper.selectList(exportReqVO);  
86 - }  
87 -  
88 -}  
89 \ No newline at end of file 0 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserServiceImplTest deleted
1 -package cn.iocoder.yudao.module.system.service.user;  
2 -  
3 -import org.junit.jupiter.api.Disabled;  
4 -import org.junit.jupiter.api.Test;  
5 -import org.springframework.boot.test.mock.mockito.MockBean;  
6 -  
7 -import javax.annotation.Resource;  
8 -  
9 -import cn.iocoder.yudao.module.framework.test.core.ut.BaseDbUnitTest;  
10 -  
11 -import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;  
12 -import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;  
13 -import cn.iocoder.yudao.module.system.dal.mysql.user.SystemUserMapper;  
14 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
15 -  
16 -import javax.annotation.Resource;  
17 -import org.springframework.context.annotation.Import;  
18 -import java.util.*;  
19 -import java.time.LocalDateTime;  
20 -  
21 -import static cn.hutool.core.util.RandomUtil.*;  
22 -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;  
23 -import static cn.iocoder.yudao.module.framework.test.core.util.AssertUtils.*;  
24 -import static cn.iocoder.yudao.module.framework.test.core.util.RandomUtils.*;  
25 -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;  
26 -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;  
27 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;  
28 -import static org.junit.jupiter.api.Assertions.*;  
29 -import static org.mockito.Mockito.*;  
30 -  
31 -/**  
32 - * {@link SystemUserServiceImpl} 的单元测试类  
33 - *  
34 - * @author 芋道源码  
35 - */  
36 -@Import(SystemUserServiceImpl.class)  
37 -public class SystemUserServiceImplTest extends BaseDbUnitTest {  
38 -  
39 - @Resource  
40 - private SystemUserServiceImpl userService;  
41 -  
42 - @Resource  
43 - private SystemUserMapper userMapper;  
44 -  
45 - @Test  
46 - public void testCreateUser_success() {  
47 - // 准备参数  
48 - SystemUserCreateReqVO reqVO = randomPojo(SystemUserCreateReqVO.class);  
49 -  
50 - // 调用  
51 - Long userId = userService.createUser(reqVO);  
52 - // 断言  
53 - assertNotNull(userId);  
54 - // 校验记录的属性是否正确  
55 - SystemUserDO user = userMapper.selectById(userId);  
56 - assertPojoEquals(reqVO, user);  
57 - }  
58 -  
59 - @Test  
60 - public void testUpdateUser_success() {  
61 - // mock 数据  
62 - SystemUserDO dbUser = randomPojo(SystemUserDO.class);  
63 - userMapper.insert(dbUser);// @Sql: 先插入出一条存在的数据  
64 - // 准备参数  
65 - SystemUserUpdateReqVO reqVO = randomPojo(SystemUserUpdateReqVO.class, o -> {  
66 - o.setId(dbUser.getId()); // 设置更新的 ID  
67 - });  
68 -  
69 - // 调用  
70 - userService.updateUser(reqVO);  
71 - // 校验是否更新正确  
72 - SystemUserDO user = userMapper.selectById(reqVO.getId()); // 获取最新的  
73 - assertPojoEquals(reqVO, user);  
74 - }  
75 -  
76 - @Test  
77 - public void testUpdateUser_notExists() {  
78 - // 准备参数  
79 - SystemUserUpdateReqVO reqVO = randomPojo(SystemUserUpdateReqVO.class);  
80 -  
81 - // 调用, 并断言异常  
82 - assertServiceException(() -> userService.updateUser(reqVO), USER_NOT_EXISTS);  
83 - }  
84 -  
85 - @Test  
86 - public void testDeleteUser_success() {  
87 - // mock 数据  
88 - SystemUserDO dbUser = randomPojo(SystemUserDO.class);  
89 - userMapper.insert(dbUser);// @Sql: 先插入出一条存在的数据  
90 - // 准备参数  
91 - Long id = dbUser.getId();  
92 -  
93 - // 调用  
94 - userService.deleteUser(id);  
95 - // 校验数据不存在了  
96 - assertNull(userMapper.selectById(id));  
97 - }  
98 -  
99 - @Test  
100 - public void testDeleteUser_notExists() {  
101 - // 准备参数  
102 - Long id = randomLongId();  
103 -  
104 - // 调用, 并断言异常  
105 - assertServiceException(() -> userService.deleteUser(id), USER_NOT_EXISTS);  
106 - }  
107 -  
108 - @Test  
109 - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解  
110 - public void testGetUserPage() {  
111 - // mock 数据  
112 - SystemUserDO dbUser = randomPojo(SystemUserDO.class, o -> { // 等会查询到  
113 - o.setName(null);  
114 - o.setSex1(null);  
115 - o.setSex2(null);  
116 - o.setSex3(null);  
117 - o.setBirthday(null);  
118 - o.setCreateTime(null);  
119 - });  
120 - userMapper.insert(dbUser);  
121 - // 测试 name 不匹配  
122 - userMapper.insert(cloneIgnoreId(dbUser, o -> o.setName(null)));  
123 - // 测试 sex1 不匹配  
124 - userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex1(null)));  
125 - // 测试 sex2 不匹配  
126 - userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex2(null)));  
127 - // 测试 sex3 不匹配  
128 - userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex3(null)));  
129 - // 测试 birthday 不匹配  
130 - userMapper.insert(cloneIgnoreId(dbUser, o -> o.setBirthday(null)));  
131 - // 测试 createTime 不匹配  
132 - userMapper.insert(cloneIgnoreId(dbUser, o -> o.setCreateTime(null)));  
133 - // 准备参数  
134 - SystemUserPageReqVO reqVO = new SystemUserPageReqVO();  
135 - reqVO.setName(null);  
136 - reqVO.setSex1(null);  
137 - reqVO.setSex2(null);  
138 - reqVO.setSex3(null);  
139 - reqVO.setBirthday(null);  
140 - reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));  
141 -  
142 - // 调用  
143 - PageResult<SystemUserDO> pageResult = userService.getUserPage(reqVO);  
144 - // 断言  
145 - assertEquals(1, pageResult.getTotal());  
146 - assertEquals(1, pageResult.getList().size());  
147 - assertPojoEquals(dbUser, pageResult.getList().get(0));  
148 - }  
149 -  
150 - @Test  
151 - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解  
152 - public void testGetUserList() {  
153 - // mock 数据  
154 - SystemUserDO dbUser = randomPojo(SystemUserDO.class, o -> { // 等会查询到  
155 - o.setName(null);  
156 - o.setSex1(null);  
157 - o.setSex2(null);  
158 - o.setSex3(null);  
159 - o.setBirthday(null);  
160 - o.setCreateTime(null);  
161 - });  
162 - userMapper.insert(dbUser);  
163 - // 测试 name 不匹配  
164 - userMapper.insert(cloneIgnoreId(dbUser, o -> o.setName(null)));  
165 - // 测试 sex1 不匹配  
166 - userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex1(null)));  
167 - // 测试 sex2 不匹配  
168 - userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex2(null)));  
169 - // 测试 sex3 不匹配  
170 - userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex3(null)));  
171 - // 测试 birthday 不匹配  
172 - userMapper.insert(cloneIgnoreId(dbUser, o -> o.setBirthday(null)));  
173 - // 测试 createTime 不匹配  
174 - userMapper.insert(cloneIgnoreId(dbUser, o -> o.setCreateTime(null)));  
175 - // 准备参数  
176 - SystemUserExportReqVO reqVO = new SystemUserExportReqVO();  
177 - reqVO.setName(null);  
178 - reqVO.setSex1(null);  
179 - reqVO.setSex2(null);  
180 - reqVO.setSex3(null);  
181 - reqVO.setBirthday(null);  
182 - reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));  
183 -  
184 - // 调用  
185 - List<SystemUserDO> list = userService.getUserList(reqVO);  
186 - // 断言  
187 - assertEquals(1, list.size());  
188 - assertPojoEquals(dbUser, list.get(0));  
189 - }  
190 -  
191 -}  
192 \ No newline at end of file 0 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/sql/h2 deleted
1 --- 将该建表 SQL 语句,添加到 yudao-module-system-biz 模块的 test/resources/sql/create_tables.sql 文件里  
2 -CREATE TABLE IF NOT EXISTS "system_user" (  
3 - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,  
4 - "name" varchar NOT NULL,  
5 - "avatar" varchar,  
6 - "video" varchar,  
7 - "description" varchar,  
8 - "sex1" varchar,  
9 - "sex2" int,  
10 - "sex3" bit,  
11 - "birthday" varchar,  
12 - "memo" varchar,  
13 - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,  
14 - PRIMARY KEY ("id")  
15 -) COMMENT '用户表';  
16 -  
17 --- 将该删表 SQL 语句,添加到 yudao-module-system-biz 模块的 test/resources/sql/clean.sql 文件里  
18 -DELETE FROM "system_user";  
19 \ No newline at end of file 0 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/vue/api deleted
1 -import request from '@/config/axios'  
2 -  
3 -export interface UserVO {  
4 - id: number  
5 - name: string  
6 - avatar: string  
7 - video: string  
8 - description: string  
9 - sex1: string  
10 - sex2: number  
11 - sex3: boolean  
12 - birthday: Date  
13 - memo: string  
14 - createTime: Date  
15 -}  
16 -  
17 -// 查询用户列表  
18 -export const getUserPage = async (params) => {  
19 - return await request.get({ url: `/system/user/page`, params })  
20 -}  
21 -  
22 -// 查询用户详情  
23 -export const getUser = async (id: number) => {  
24 - return await request.get({ url: `/system/user/get?id=` + id })  
25 -}  
26 -  
27 -// 新增用户  
28 -export const createUser = async (data: UserVO) => {  
29 - return await request.post({ url: `/system/user/create`, data })  
30 -}  
31 -  
32 -// 修改用户  
33 -export const updateUser = async (data: UserVO) => {  
34 - return await request.put({ url: `/system/user/update`, data })  
35 -}  
36 -  
37 -// 删除用户  
38 -export const deleteUser = async (id: number) => {  
39 - return await request.delete({ url: `/system/user/delete?id=` + id })  
40 -}  
41 -  
42 -// 导出用户 Excel  
43 -export const exportUser = async (params) => {  
44 - return await request.download({ url: `/system/user/export-excel`, params })  
45 -}  
46 \ No newline at end of file 0 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/assert.json 0 → 100644
  1 +[ {
  2 + "contentPath" : "java/InfraStudentPageReqVO",
  3 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java"
  4 +}, {
  5 + "contentPath" : "java/InfraStudentRespVO",
  6 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java"
  7 +}, {
  8 + "contentPath" : "java/InfraStudentSaveReqVO",
  9 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java"
  10 +}, {
  11 + "contentPath" : "java/InfraStudentController",
  12 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java"
  13 +}, {
  14 + "contentPath" : "java/InfraStudentDO",
  15 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java"
  16 +}, {
  17 + "contentPath" : "java/InfraStudentContactDO",
  18 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java"
  19 +}, {
  20 + "contentPath" : "java/InfraStudentTeacherDO",
  21 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java"
  22 +}, {
  23 + "contentPath" : "java/InfraStudentMapper",
  24 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java"
  25 +}, {
  26 + "contentPath" : "java/InfraStudentContactMapper",
  27 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java"
  28 +}, {
  29 + "contentPath" : "java/InfraStudentTeacherMapper",
  30 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java"
  31 +}, {
  32 + "contentPath" : "xml/InfraStudentMapper",
  33 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml"
  34 +}, {
  35 + "contentPath" : "java/InfraStudentServiceImpl",
  36 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java"
  37 +}, {
  38 + "contentPath" : "java/InfraStudentService",
  39 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java"
  40 +}, {
  41 + "contentPath" : "java/InfraStudentServiceImplTest",
  42 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java"
  43 +}, {
  44 + "contentPath" : "java/ErrorCodeConstants_手动操作",
  45 + "filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java"
  46 +}, {
  47 + "contentPath" : "sql/sql",
  48 + "filePath" : "sql/sql.sql"
  49 +}, {
  50 + "contentPath" : "sql/h2",
  51 + "filePath" : "sql/h2.sql"
  52 +}, {
  53 + "contentPath" : "vue/index",
  54 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue"
  55 +}, {
  56 + "contentPath" : "vue/StudentForm",
  57 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/StudentForm.vue"
  58 +}, {
  59 + "contentPath" : "vue/StudentContactForm",
  60 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactForm.vue"
  61 +}, {
  62 + "contentPath" : "vue/StudentTeacherForm",
  63 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherForm.vue"
  64 +}, {
  65 + "contentPath" : "vue/StudentContactList",
  66 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactList.vue"
  67 +}, {
  68 + "contentPath" : "vue/StudentTeacherList",
  69 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherList.vue"
  70 +}, {
  71 + "contentPath" : "ts/index",
  72 + "filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts"
  73 +} ]
0 \ No newline at end of file 74 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/ErrorCodeConstants_手动操作 0 → 100644
  1 +// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!!
  2 +// ========== 学生 TODO 补充编号 ==========
  3 +ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在");
  4 +ErrorCode STUDENT_CONTACT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生联系人不存在");
  5 +ErrorCode STUDENT_TEACHER_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生班主任不存在");
  6 +ErrorCode STUDENT_TEACHER_EXISTS = new ErrorCode(TODO 补充编号, "学生班主任已存在");
0 \ No newline at end of file 7 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserDO renamed to yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentContactDO
1 -package cn.iocoder.yudao.module.system.dal.dataobject.user; 1 +package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
2 2
3 import lombok.*; 3 import lombok.*;
4 import java.util.*; 4 import java.util.*;
@@ -8,19 +8,19 @@ import com.baomidou.mybatisplus.annotation.*; @@ -8,19 +8,19 @@ import com.baomidou.mybatisplus.annotation.*;
8 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 8 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
9 9
10 /** 10 /**
11 - * 用户 DO 11 + * 学生联系人 DO
12 * 12 *
13 * @author 芋道源码 13 * @author 芋道源码
14 */ 14 */
15 -@TableName("system_user")  
16 -@KeySequence("system_user_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 15 +@TableName("infra_student_contact")
  16 +@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
17 @Data 17 @Data
18 @EqualsAndHashCode(callSuper = true) 18 @EqualsAndHashCode(callSuper = true)
19 @ToString(callSuper = true) 19 @ToString(callSuper = true)
20 @Builder 20 @Builder
21 @NoArgsConstructor 21 @NoArgsConstructor
22 @AllArgsConstructor 22 @AllArgsConstructor
23 -public class SystemUserDO extends BaseDO { 23 +public class InfraStudentContactDO extends BaseDO {
24 24
25 /** 25 /**
26 * 编号 26 * 编号
@@ -28,43 +28,41 @@ public class SystemUserDO extends BaseDO { @@ -28,43 +28,41 @@ public class SystemUserDO extends BaseDO {
28 @TableId 28 @TableId
29 private Long id; 29 private Long id;
30 /** 30 /**
31 - * 名字 31 + * 学生编号
32 */ 32 */
33 - private String name; 33 + private Long studentId;
34 /** 34 /**
35 - * 头像 35 + * 名字
36 */ 36 */
37 - private String avatar; 37 + private String name;
38 /** 38 /**
39 - * 视频 39 + * 简介
40 */ 40 */
41 - private String video; 41 + private String description;
42 /** 42 /**
43 - * 个人简介 43 + * 出生日期
44 */ 44 */
45 - private String description; 45 + private LocalDateTime birthday;
46 /** 46 /**
47 - * 性别 1 47 + * 性别
48 * 48 *
49 - * 枚举 {@link TODO system_sex1 对应的类} 49 + * 枚举 {@link TODO system_user_sex 对应的类}
50 */ 50 */
51 - private String sex1; 51 + private Integer sex;
52 /** 52 /**
53 - * 性别 2 53 + * 是否有效
54 * 54 *
55 - * 枚举 {@link TODO system_sex2 对应的类} 55 + * 枚举 {@link TODO infra_boolean_string 对应的类}
56 */ 56 */
57 - private Integer sex2; 57 + private Boolean enabled;
58 /** 58 /**
59 - * 性别 3  
60 - *  
61 - * 枚举 {@link TODO system_sex3 对应的类} 59 + * 头像
62 */ 60 */
63 - private Boolean sex3; 61 + private String avatar;
64 /** 62 /**
65 - * 出生日期 63 + * 附件
66 */ 64 */
67 - private LocalDateTime birthday; 65 + private String video;
68 /** 66 /**
69 * 备注 67 * 备注
70 */ 68 */
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentContactMapper 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.mysql.demo;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  8 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  9 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  10 +import org.apache.ibatis.annotations.Mapper;
  11 +
  12 +/**
  13 + * 学生联系人 Mapper
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Mapper
  18 +public interface InfraStudentContactMapper extends BaseMapperX<InfraStudentContactDO> {
  19 +
  20 + default PageResult<InfraStudentContactDO> selectPage(PageParam reqVO, Long studentId) {
  21 + return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentContactDO>()
  22 + .eq(InfraStudentContactDO::getStudentId, studentId)
  23 + .orderByDesc(InfraStudentContactDO::getId));
  24 + }
  25 +
  26 + default int deleteByStudentId(Long studentId) {
  27 + return delete(InfraStudentContactDO::getStudentId, studentId);
  28 + }
  29 +
  30 +}
0 \ No newline at end of file 31 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentController 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.controller.admin.demo;
  2 +
  3 +import org.springframework.web.bind.annotation.*;
  4 +import javax.annotation.Resource;
  5 +import org.springframework.validation.annotation.Validated;
  6 +import org.springframework.security.access.prepost.PreAuthorize;
  7 +import io.swagger.v3.oas.annotations.tags.Tag;
  8 +import io.swagger.v3.oas.annotations.Parameter;
  9 +import io.swagger.v3.oas.annotations.Operation;
  10 +
  11 +import javax.validation.constraints.*;
  12 +import javax.validation.*;
  13 +import javax.servlet.http.*;
  14 +import java.util.*;
  15 +import java.io.IOException;
  16 +
  17 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  18 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  19 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  20 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  21 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  22 +
  23 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  24 +
  25 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
  26 +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
  27 +
  28 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  29 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  30 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  31 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  32 +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService;
  33 +
  34 +@Tag(name = "管理后台 - 学生")
  35 +@RestController
  36 +@RequestMapping("/infra/student")
  37 +@Validated
  38 +public class InfraStudentController {
  39 +
  40 + @Resource
  41 + private InfraStudentService studentService;
  42 +
  43 + @PostMapping("/create")
  44 + @Operation(summary = "创建学生")
  45 + @PreAuthorize("@ss.hasPermission('infra:student:create')")
  46 + public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) {
  47 + return success(studentService.createStudent(createReqVO));
  48 + }
  49 +
  50 + @PutMapping("/update")
  51 + @Operation(summary = "更新学生")
  52 + @PreAuthorize("@ss.hasPermission('infra:student:update')")
  53 + public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) {
  54 + studentService.updateStudent(updateReqVO);
  55 + return success(true);
  56 + }
  57 +
  58 + @DeleteMapping("/delete")
  59 + @Operation(summary = "删除学生")
  60 + @Parameter(name = "id", description = "编号", required = true)
  61 + @PreAuthorize("@ss.hasPermission('infra:student:delete')")
  62 + public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) {
  63 + studentService.deleteStudent(id);
  64 + return success(true);
  65 + }
  66 +
  67 + @GetMapping("/get")
  68 + @Operation(summary = "获得学生")
  69 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  70 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  71 + public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) {
  72 + InfraStudentDO student = studentService.getStudent(id);
  73 + return success(BeanUtils.toBean(student, InfraStudentRespVO.class));
  74 + }
  75 +
  76 + @GetMapping("/page")
  77 + @Operation(summary = "获得学生分页")
  78 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  79 + public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) {
  80 + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO);
  81 + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class));
  82 + }
  83 +
  84 + @GetMapping("/export-excel")
  85 + @Operation(summary = "导出学生 Excel")
  86 + @PreAuthorize("@ss.hasPermission('infra:student:export')")
  87 + @OperateLog(type = EXPORT)
  88 + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO,
  89 + HttpServletResponse response) throws IOException {
  90 + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
  91 + List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList();
  92 + // 导出 Excel
  93 + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class,
  94 + BeanUtils.toBean(list, InfraStudentRespVO.class));
  95 + }
  96 +
  97 + // ==================== 子表(学生联系人) ====================
  98 +
  99 + @GetMapping("/student-contact/page")
  100 + @Operation(summary = "获得学生联系人分页")
  101 + @Parameter(name = "studentId", description = "学生编号")
  102 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  103 + public CommonResult<PageResult<InfraStudentContactDO>> getStudentContactPage(PageParam pageReqVO,
  104 + @RequestParam("studentId") Long studentId) {
  105 + return success(studentService.getStudentContactPage(pageReqVO, studentId));
  106 + }
  107 +
  108 + @PostMapping("/student-contact/create")
  109 + @Operation(summary = "创建学生联系人")
  110 + @PreAuthorize("@ss.hasPermission('infra:student:create')")
  111 + public CommonResult<Long> createStudentContact(@Valid @RequestBody InfraStudentContactDO studentContact) {
  112 + return success(studentService.createStudentContact(studentContact));
  113 + }
  114 +
  115 + @PutMapping("/student-contact/update")
  116 + @Operation(summary = "更新学生联系人")
  117 + @PreAuthorize("@ss.hasPermission('infra:student:update')")
  118 + public CommonResult<Boolean> updateStudentContact(@Valid @RequestBody InfraStudentContactDO studentContact) {
  119 + studentService.updateStudentContact(studentContact);
  120 + return success(true);
  121 + }
  122 +
  123 + @DeleteMapping("/student-contact/delete")
  124 + @Parameter(name = "id", description = "编号", required = true)
  125 + @Operation(summary = "删除学生联系人")
  126 + @PreAuthorize("@ss.hasPermission('infra:student:delete')")
  127 + public CommonResult<Boolean> deleteStudentContact(@RequestParam("id") Long id) {
  128 + studentService.deleteStudentContact(id);
  129 + return success(true);
  130 + }
  131 +
  132 + @GetMapping("/student-contact/get")
  133 + @Operation(summary = "获得学生联系人")
  134 + @Parameter(name = "id", description = "编号", required = true)
  135 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  136 + public CommonResult<InfraStudentContactDO> getStudentContact(@RequestParam("id") Long id) {
  137 + return success(studentService.getStudentContact(id));
  138 + }
  139 +
  140 + // ==================== 子表(学生班主任) ====================
  141 +
  142 + @GetMapping("/student-teacher/page")
  143 + @Operation(summary = "获得学生班主任分页")
  144 + @Parameter(name = "studentId", description = "学生编号")
  145 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  146 + public CommonResult<PageResult<InfraStudentTeacherDO>> getStudentTeacherPage(PageParam pageReqVO,
  147 + @RequestParam("studentId") Long studentId) {
  148 + return success(studentService.getStudentTeacherPage(pageReqVO, studentId));
  149 + }
  150 +
  151 + @PostMapping("/student-teacher/create")
  152 + @Operation(summary = "创建学生班主任")
  153 + @PreAuthorize("@ss.hasPermission('infra:student:create')")
  154 + public CommonResult<Long> createStudentTeacher(@Valid @RequestBody InfraStudentTeacherDO studentTeacher) {
  155 + return success(studentService.createStudentTeacher(studentTeacher));
  156 + }
  157 +
  158 + @PutMapping("/student-teacher/update")
  159 + @Operation(summary = "更新学生班主任")
  160 + @PreAuthorize("@ss.hasPermission('infra:student:update')")
  161 + public CommonResult<Boolean> updateStudentTeacher(@Valid @RequestBody InfraStudentTeacherDO studentTeacher) {
  162 + studentService.updateStudentTeacher(studentTeacher);
  163 + return success(true);
  164 + }
  165 +
  166 + @DeleteMapping("/student-teacher/delete")
  167 + @Parameter(name = "id", description = "编号", required = true)
  168 + @Operation(summary = "删除学生班主任")
  169 + @PreAuthorize("@ss.hasPermission('infra:student:delete')")
  170 + public CommonResult<Boolean> deleteStudentTeacher(@RequestParam("id") Long id) {
  171 + studentService.deleteStudentTeacher(id);
  172 + return success(true);
  173 + }
  174 +
  175 + @GetMapping("/student-teacher/get")
  176 + @Operation(summary = "获得学生班主任")
  177 + @Parameter(name = "id", description = "编号", required = true)
  178 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  179 + public CommonResult<InfraStudentTeacherDO> getStudentTeacher(@RequestParam("id") Long id) {
  180 + return success(studentService.getStudentTeacher(id));
  181 + }
  182 +
  183 +}
0 \ No newline at end of file 184 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentDO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import java.time.LocalDateTime;
  6 +import java.time.LocalDateTime;
  7 +import com.baomidou.mybatisplus.annotation.*;
  8 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  9 +
  10 +/**
  11 + * 学生 DO
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@TableName("infra_student")
  16 +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class InfraStudentDO extends BaseDO {
  24 +
  25 + /**
  26 + * 编号
  27 + */
  28 + @TableId
  29 + private Long id;
  30 + /**
  31 + * 名字
  32 + */
  33 + private String name;
  34 + /**
  35 + * 简介
  36 + */
  37 + private String description;
  38 + /**
  39 + * 出生日期
  40 + */
  41 + private LocalDateTime birthday;
  42 + /**
  43 + * 性别
  44 + *
  45 + * 枚举 {@link TODO system_user_sex 对应的类}
  46 + */
  47 + private Integer sex;
  48 + /**
  49 + * 是否有效
  50 + *
  51 + * 枚举 {@link TODO infra_boolean_string 对应的类}
  52 + */
  53 + private Boolean enabled;
  54 + /**
  55 + * 头像
  56 + */
  57 + private String avatar;
  58 + /**
  59 + * 附件
  60 + */
  61 + private String video;
  62 + /**
  63 + * 备注
  64 + */
  65 + private String memo;
  66 +
  67 +}
0 \ No newline at end of file 68 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentMapper 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.mysql.demo;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  7 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  8 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  9 +import org.apache.ibatis.annotations.Mapper;
  10 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  11 +
  12 +/**
  13 + * 学生 Mapper
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Mapper
  18 +public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> {
  19 +
  20 + default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) {
  21 + return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>()
  22 + .likeIfPresent(InfraStudentDO::getName, reqVO.getName())
  23 + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday())
  24 + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex())
  25 + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled())
  26 + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime())
  27 + .orderByDesc(InfraStudentDO::getId));
  28 + }
  29 +
  30 +}
0 \ No newline at end of file 31 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserPageReqVO renamed to yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentPageReqVO
1 -package cn.iocoder.yudao.module.system.controller.admin.user.vo; 1 +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
2 2
3 import lombok.*; 3 import lombok.*;
4 import java.util.*; 4 import java.util.*;
@@ -9,27 +9,24 @@ import java.time.LocalDateTime; @@ -9,27 +9,24 @@ import java.time.LocalDateTime;
9 9
10 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 10 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
11 11
12 -@Schema(description = "管理后台 - 用户分页 Request VO") 12 +@Schema(description = "管理后台 - 学生分页 Request VO")
13 @Data 13 @Data
14 @EqualsAndHashCode(callSuper = true) 14 @EqualsAndHashCode(callSuper = true)
15 @ToString(callSuper = true) 15 @ToString(callSuper = true)
16 -public class SystemUserPageReqVO extends PageParam { 16 +public class InfraStudentPageReqVO extends PageParam {
17 17
18 @Schema(description = "名字", example = "芋头") 18 @Schema(description = "名字", example = "芋头")
19 private String name; 19 private String name;
20 20
21 - @Schema(description = "性别 1", example = "男")  
22 - private String sex1;  
23 -  
24 - @Schema(description = "性别 2", example = "1")  
25 - private Integer sex2;  
26 -  
27 - @Schema(description = "性别 3", example = "true")  
28 - private Boolean sex3;  
29 -  
30 @Schema(description = "出生日期") 21 @Schema(description = "出生日期")
31 private LocalDateTime birthday; 22 private LocalDateTime birthday;
32 23
  24 + @Schema(description = "性别", example = "1")
  25 + private Integer sex;
  26 +
  27 + @Schema(description = "是否有效", example = "true")
  28 + private Boolean enabled;
  29 +
33 @Schema(description = "创建时间") 30 @Schema(description = "创建时间")
34 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 31 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
35 private LocalDateTime[] createTime; 32 private LocalDateTime[] createTime;
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentRespVO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import java.util.*;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +import java.time.LocalDateTime;
  9 +import com.alibaba.excel.annotation.*;
  10 +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
  11 +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
  12 +
  13 +@Schema(description = "管理后台 - 学生 Response VO")
  14 +@Data
  15 +@ExcelIgnoreUnannotated
  16 +public class InfraStudentRespVO {
  17 +
  18 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  19 + @ExcelProperty("编号")
  20 + private Long id;
  21 +
  22 + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
  23 + @ExcelProperty("名字")
  24 + private String name;
  25 +
  26 + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
  27 + @ExcelProperty("简介")
  28 + private String description;
  29 +
  30 + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
  31 + @ExcelProperty("出生日期")
  32 + private LocalDateTime birthday;
  33 +
  34 + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  35 + @ExcelProperty(value = "性别", converter = DictConvert.class)
  36 + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
  37 + private Integer sex;
  38 +
  39 + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  40 + @ExcelProperty(value = "是否有效", converter = DictConvert.class)
  41 + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
  42 + private Boolean enabled;
  43 +
  44 + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
  45 + @ExcelProperty("头像")
  46 + private String avatar;
  47 +
  48 + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
  49 + @ExcelProperty("附件")
  50 + private String video;
  51 +
  52 + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
  53 + @ExcelProperty("备注")
  54 + private String memo;
  55 +
  56 + @Schema(description = "创建时间")
  57 + @ExcelProperty("创建时间")
  58 + private LocalDateTime createTime;
  59 +
  60 +}
0 \ No newline at end of file 61 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentSaveReqVO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import javax.validation.constraints.*;
  7 +import java.util.*;
  8 +import org.springframework.format.annotation.DateTimeFormat;
  9 +import java.time.LocalDateTime;
  10 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  11 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  12 +
  13 +@Schema(description = "管理后台 - 学生新增/修改 Request VO")
  14 +@Data
  15 +public class InfraStudentSaveReqVO {
  16 +
  17 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  18 + private Long id;
  19 +
  20 + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
  21 + @NotEmpty(message = "名字不能为空")
  22 + private String name;
  23 +
  24 + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
  25 + @NotEmpty(message = "简介不能为空")
  26 + private String description;
  27 +
  28 + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
  29 + @NotNull(message = "出生日期不能为空")
  30 + private LocalDateTime birthday;
  31 +
  32 + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  33 + @NotNull(message = "性别不能为空")
  34 + private Integer sex;
  35 +
  36 + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  37 + @NotNull(message = "是否有效不能为空")
  38 + private Boolean enabled;
  39 +
  40 + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
  41 + @NotEmpty(message = "头像不能为空")
  42 + private String avatar;
  43 +
  44 + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
  45 + @NotEmpty(message = "附件不能为空")
  46 + private String video;
  47 +
  48 + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
  49 + @NotEmpty(message = "备注不能为空")
  50 + private String memo;
  51 +
  52 +}
0 \ No newline at end of file 53 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentService 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.service.demo;
  2 +
  3 +import java.util.*;
  4 +import javax.validation.*;
  5 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  6 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  7 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  8 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  9 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  10 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  11 +
  12 +/**
  13 + * 学生 Service 接口
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +public interface InfraStudentService {
  18 +
  19 + /**
  20 + * 创建学生
  21 + *
  22 + * @param createReqVO 创建信息
  23 + * @return 编号
  24 + */
  25 + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO);
  26 +
  27 + /**
  28 + * 更新学生
  29 + *
  30 + * @param updateReqVO 更新信息
  31 + */
  32 + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO);
  33 +
  34 + /**
  35 + * 删除学生
  36 + *
  37 + * @param id 编号
  38 + */
  39 + void deleteStudent(Long id);
  40 +
  41 + /**
  42 + * 获得学生
  43 + *
  44 + * @param id 编号
  45 + * @return 学生
  46 + */
  47 + InfraStudentDO getStudent(Long id);
  48 +
  49 + /**
  50 + * 获得学生分页
  51 + *
  52 + * @param pageReqVO 分页查询
  53 + * @return 学生分页
  54 + */
  55 + PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO);
  56 +
  57 + // ==================== 子表(学生联系人) ====================
  58 +
  59 + /**
  60 + * 获得学生联系人分页
  61 + *
  62 + * @param pageReqVO 分页查询
  63 + * @param studentId 学生编号
  64 + * @return 学生联系人分页
  65 + */
  66 + PageResult<InfraStudentContactDO> getStudentContactPage(PageParam pageReqVO, Long studentId);
  67 +
  68 + /**
  69 + * 创建学生联系人
  70 + *
  71 + * @param studentContact 创建信息
  72 + * @return 编号
  73 + */
  74 + Long createStudentContact(@Valid InfraStudentContactDO studentContact);
  75 +
  76 + /**
  77 + * 更新学生联系人
  78 + *
  79 + * @param studentContact 更新信息
  80 + */
  81 + void updateStudentContact(@Valid InfraStudentContactDO studentContact);
  82 +
  83 + /**
  84 + * 删除学生联系人
  85 + *
  86 + * @param id 编号
  87 + */
  88 + void deleteStudentContact(Long id);
  89 +
  90 + /**
  91 + * 获得学生联系人
  92 + *
  93 + * @param id 编号
  94 + * @return 学生联系人
  95 + */
  96 + InfraStudentContactDO getStudentContact(Long id);
  97 +
  98 + // ==================== 子表(学生班主任) ====================
  99 +
  100 + /**
  101 + * 获得学生班主任分页
  102 + *
  103 + * @param pageReqVO 分页查询
  104 + * @param studentId 学生编号
  105 + * @return 学生班主任分页
  106 + */
  107 + PageResult<InfraStudentTeacherDO> getStudentTeacherPage(PageParam pageReqVO, Long studentId);
  108 +
  109 + /**
  110 + * 创建学生班主任
  111 + *
  112 + * @param studentTeacher 创建信息
  113 + * @return 编号
  114 + */
  115 + Long createStudentTeacher(@Valid InfraStudentTeacherDO studentTeacher);
  116 +
  117 + /**
  118 + * 更新学生班主任
  119 + *
  120 + * @param studentTeacher 更新信息
  121 + */
  122 + void updateStudentTeacher(@Valid InfraStudentTeacherDO studentTeacher);
  123 +
  124 + /**
  125 + * 删除学生班主任
  126 + *
  127 + * @param id 编号
  128 + */
  129 + void deleteStudentTeacher(Long id);
  130 +
  131 + /**
  132 + * 获得学生班主任
  133 + *
  134 + * @param id 编号
  135 + * @return 学生班主任
  136 + */
  137 + InfraStudentTeacherDO getStudentTeacher(Long id);
  138 +
  139 +}
0 \ No newline at end of file 140 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentServiceImpl 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.service.demo;
  2 +
  3 +import org.springframework.stereotype.Service;
  4 +import javax.annotation.Resource;
  5 +import org.springframework.validation.annotation.Validated;
  6 +import org.springframework.transaction.annotation.Transactional;
  7 +
  8 +import java.util.*;
  9 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  10 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  11 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  12 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  13 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  14 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  15 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  16 +
  17 +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
  18 +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper;
  19 +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper;
  20 +
  21 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  22 +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
  23 +
  24 +/**
  25 + * 学生 Service 实现类
  26 + *
  27 + * @author 芋道源码
  28 + */
  29 +@Service
  30 +@Validated
  31 +public class InfraStudentServiceImpl implements InfraStudentService {
  32 +
  33 + @Resource
  34 + private InfraStudentMapper studentMapper;
  35 + @Resource
  36 + private InfraStudentContactMapper studentContactMapper;
  37 + @Resource
  38 + private InfraStudentTeacherMapper studentTeacherMapper;
  39 +
  40 + @Override
  41 + public Long createStudent(InfraStudentSaveReqVO createReqVO) {
  42 + // 插入
  43 + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class);
  44 + studentMapper.insert(student);
  45 + // 返回
  46 + return student.getId();
  47 + }
  48 +
  49 + @Override
  50 + public void updateStudent(InfraStudentSaveReqVO updateReqVO) {
  51 + // 校验存在
  52 + validateStudentExists(updateReqVO.getId());
  53 + // 更新
  54 + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class);
  55 + studentMapper.updateById(updateObj);
  56 + }
  57 +
  58 + @Override
  59 + @Transactional(rollbackFor = Exception.class)
  60 + public void deleteStudent(Long id) {
  61 + // 校验存在
  62 + validateStudentExists(id);
  63 + // 删除
  64 + studentMapper.deleteById(id);
  65 +
  66 + // 删除子表
  67 + deleteStudentContactByStudentId(id);
  68 + deleteStudentTeacherByStudentId(id);
  69 + }
  70 +
  71 + private void validateStudentExists(Long id) {
  72 + if (studentMapper.selectById(id) == null) {
  73 + throw exception(STUDENT_NOT_EXISTS);
  74 + }
  75 + }
  76 +
  77 + @Override
  78 + public InfraStudentDO getStudent(Long id) {
  79 + return studentMapper.selectById(id);
  80 + }
  81 +
  82 + @Override
  83 + public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) {
  84 + return studentMapper.selectPage(pageReqVO);
  85 + }
  86 +
  87 + // ==================== 子表(学生联系人) ====================
  88 +
  89 + @Override
  90 + public PageResult<InfraStudentContactDO> getStudentContactPage(PageParam pageReqVO, Long studentId) {
  91 + return studentContactMapper.selectPage(pageReqVO, studentId);
  92 + }
  93 +
  94 + @Override
  95 + public Long createStudentContact(InfraStudentContactDO studentContact) {
  96 + studentContactMapper.insert(studentContact);
  97 + return studentContact.getId();
  98 + }
  99 +
  100 + @Override
  101 + public void updateStudentContact(InfraStudentContactDO studentContact) {
  102 + // 校验存在
  103 + validateStudentContactExists(studentContact.getId());
  104 + // 更新
  105 + studentContactMapper.updateById(studentContact);
  106 + }
  107 +
  108 + @Override
  109 + public void deleteStudentContact(Long id) {
  110 + // 校验存在
  111 + validateStudentContactExists(id);
  112 + // 删除
  113 + studentContactMapper.deleteById(id);
  114 + }
  115 +
  116 + @Override
  117 + public InfraStudentContactDO getStudentContact(Long id) {
  118 + return studentContactMapper.selectById(id);
  119 + }
  120 +
  121 + private void validateStudentContactExists(Long id) {
  122 + if (studentContactMapper.selectById(id) == null) {
  123 + throw exception(STUDENT_CONTACT_NOT_EXISTS);
  124 + }
  125 + }
  126 +
  127 + private void deleteStudentContactByStudentId(Long studentId) {
  128 + studentContactMapper.deleteByStudentId(studentId);
  129 + }
  130 +
  131 + // ==================== 子表(学生班主任) ====================
  132 +
  133 + @Override
  134 + public PageResult<InfraStudentTeacherDO> getStudentTeacherPage(PageParam pageReqVO, Long studentId) {
  135 + return studentTeacherMapper.selectPage(pageReqVO, studentId);
  136 + }
  137 +
  138 + @Override
  139 + public Long createStudentTeacher(InfraStudentTeacherDO studentTeacher) {
  140 + // 校验是否已经存在
  141 + if (studentTeacherMapper.selectByStudentId(studentTeacher.getStudentId()) != null) {
  142 + throw exception(STUDENT_TEACHER_EXISTS);
  143 + }
  144 + // 插入
  145 + studentTeacherMapper.insert(studentTeacher);
  146 + return studentTeacher.getId();
  147 + }
  148 +
  149 + @Override
  150 + public void updateStudentTeacher(InfraStudentTeacherDO studentTeacher) {
  151 + // 校验存在
  152 + validateStudentTeacherExists(studentTeacher.getId());
  153 + // 更新
  154 + studentTeacherMapper.updateById(studentTeacher);
  155 + }
  156 +
  157 + @Override
  158 + public void deleteStudentTeacher(Long id) {
  159 + // 校验存在
  160 + validateStudentTeacherExists(id);
  161 + // 删除
  162 + studentTeacherMapper.deleteById(id);
  163 + }
  164 +
  165 + @Override
  166 + public InfraStudentTeacherDO getStudentTeacher(Long id) {
  167 + return studentTeacherMapper.selectById(id);
  168 + }
  169 +
  170 + private void validateStudentTeacherExists(Long id) {
  171 + if (studentTeacherMapper.selectById(id) == null) {
  172 + throw exception(STUDENT_TEACHER_NOT_EXISTS);
  173 + }
  174 + }
  175 +
  176 + private void deleteStudentTeacherByStudentId(Long studentId) {
  177 + studentTeacherMapper.deleteByStudentId(studentId);
  178 + }
  179 +
  180 +}
0 \ No newline at end of file 181 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentServiceImplTest 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.service.demo;
  2 +
  3 +import org.junit.jupiter.api.Disabled;
  4 +import org.junit.jupiter.api.Test;
  5 +import org.springframework.boot.test.mock.mockito.MockBean;
  6 +
  7 +import javax.annotation.Resource;
  8 +
  9 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  10 +
  11 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  12 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  13 +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
  14 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  15 +
  16 +import javax.annotation.Resource;
  17 +import org.springframework.context.annotation.Import;
  18 +import java.util.*;
  19 +import java.time.LocalDateTime;
  20 +
  21 +import static cn.hutool.core.util.RandomUtil.*;
  22 +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
  23 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
  24 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
  25 +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
  26 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
  27 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
  28 +import static org.junit.jupiter.api.Assertions.*;
  29 +import static org.mockito.Mockito.*;
  30 +
  31 +/**
  32 + * {@link InfraStudentServiceImpl} 的单元测试类
  33 + *
  34 + * @author 芋道源码
  35 + */
  36 +@Import(InfraStudentServiceImpl.class)
  37 +public class InfraStudentServiceImplTest extends BaseDbUnitTest {
  38 +
  39 + @Resource
  40 + private InfraStudentServiceImpl studentService;
  41 +
  42 + @Resource
  43 + private InfraStudentMapper studentMapper;
  44 +
  45 + @Test
  46 + public void testCreateStudent_success() {
  47 + // 准备参数
  48 + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null);
  49 +
  50 + // 调用
  51 + Long studentId = studentService.createStudent(createReqVO);
  52 + // 断言
  53 + assertNotNull(studentId);
  54 + // 校验记录的属性是否正确
  55 + InfraStudentDO student = studentMapper.selectById(studentId);
  56 + assertPojoEquals(createReqVO, student, "id");
  57 + }
  58 +
  59 + @Test
  60 + public void testUpdateStudent_success() {
  61 + // mock 数据
  62 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
  63 + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
  64 + // 准备参数
  65 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> {
  66 + o.setId(dbStudent.getId()); // 设置更新的 ID
  67 + });
  68 +
  69 + // 调用
  70 + studentService.updateStudent(updateReqVO);
  71 + // 校验是否更新正确
  72 + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的
  73 + assertPojoEquals(updateReqVO, student);
  74 + }
  75 +
  76 + @Test
  77 + public void testUpdateStudent_notExists() {
  78 + // 准备参数
  79 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class);
  80 +
  81 + // 调用, 并断言异常
  82 + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS);
  83 + }
  84 +
  85 + @Test
  86 + public void testDeleteStudent_success() {
  87 + // mock 数据
  88 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
  89 + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
  90 + // 准备参数
  91 + Long id = dbStudent.getId();
  92 +
  93 + // 调用
  94 + studentService.deleteStudent(id);
  95 + // 校验数据不存在了
  96 + assertNull(studentMapper.selectById(id));
  97 + }
  98 +
  99 + @Test
  100 + public void testDeleteStudent_notExists() {
  101 + // 准备参数
  102 + Long id = randomLongId();
  103 +
  104 + // 调用, 并断言异常
  105 + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS);
  106 + }
  107 +
  108 + @Test
  109 + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
  110 + public void testGetStudentPage() {
  111 + // mock 数据
  112 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到
  113 + o.setName(null);
  114 + o.setBirthday(null);
  115 + o.setSex(null);
  116 + o.setEnabled(null);
  117 + o.setCreateTime(null);
  118 + });
  119 + studentMapper.insert(dbStudent);
  120 + // 测试 name 不匹配
  121 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null)));
  122 + // 测试 birthday 不匹配
  123 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null)));
  124 + // 测试 sex 不匹配
  125 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null)));
  126 + // 测试 enabled 不匹配
  127 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null)));
  128 + // 测试 createTime 不匹配
  129 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null)));
  130 + // 准备参数
  131 + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO();
  132 + reqVO.setName(null);
  133 + reqVO.setBirthday(null);
  134 + reqVO.setSex(null);
  135 + reqVO.setEnabled(null);
  136 + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
  137 +
  138 + // 调用
  139 + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(reqVO);
  140 + // 断言
  141 + assertEquals(1, pageResult.getTotal());
  142 + assertEquals(1, pageResult.getList().size());
  143 + assertPojoEquals(dbStudent, pageResult.getList().get(0));
  144 + }
  145 +
  146 +}
0 \ No newline at end of file 147 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentTeacherDO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import java.time.LocalDateTime;
  6 +import java.time.LocalDateTime;
  7 +import com.baomidou.mybatisplus.annotation.*;
  8 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  9 +
  10 +/**
  11 + * 学生班主任 DO
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@TableName("infra_student_teacher")
  16 +@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class InfraStudentTeacherDO extends BaseDO {
  24 +
  25 + /**
  26 + * 编号
  27 + */
  28 + @TableId
  29 + private Long id;
  30 + /**
  31 + * 学生编号
  32 + */
  33 + private Long studentId;
  34 + /**
  35 + * 名字
  36 + */
  37 + private String name;
  38 + /**
  39 + * 简介
  40 + */
  41 + private String description;
  42 + /**
  43 + * 出生日期
  44 + */
  45 + private LocalDateTime birthday;
  46 + /**
  47 + * 性别
  48 + *
  49 + * 枚举 {@link TODO system_user_sex 对应的类}
  50 + */
  51 + private Integer sex;
  52 + /**
  53 + * 是否有效
  54 + *
  55 + * 枚举 {@link TODO infra_boolean_string 对应的类}
  56 + */
  57 + private Boolean enabled;
  58 + /**
  59 + * 头像
  60 + */
  61 + private String avatar;
  62 + /**
  63 + * 附件
  64 + */
  65 + private String video;
  66 + /**
  67 + * 备注
  68 + */
  69 + private String memo;
  70 +
  71 +}
0 \ No newline at end of file 72 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentTeacherMapper 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.mysql.demo;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  8 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  9 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  10 +import org.apache.ibatis.annotations.Mapper;
  11 +
  12 +/**
  13 + * 学生班主任 Mapper
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Mapper
  18 +public interface InfraStudentTeacherMapper extends BaseMapperX<InfraStudentTeacherDO> {
  19 +
  20 + default PageResult<InfraStudentTeacherDO> selectPage(PageParam reqVO, Long studentId) {
  21 + return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentTeacherDO>()
  22 + .eq(InfraStudentTeacherDO::getStudentId, studentId)
  23 + .orderByDesc(InfraStudentTeacherDO::getId));
  24 + }
  25 +
  26 + default int deleteByStudentId(Long studentId) {
  27 + return delete(InfraStudentTeacherDO::getStudentId, studentId);
  28 + }
  29 +
  30 +}
0 \ No newline at end of file 31 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/sql/h2 0 → 100644
  1 +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里
  2 +CREATE TABLE IF NOT EXISTS "infra_student" (
  3 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  4 + "name" varchar NOT NULL,
  5 + "description" varchar NOT NULL,
  6 + "birthday" varchar NOT NULL,
  7 + "sex" int NOT NULL,
  8 + "enabled" bit NOT NULL,
  9 + "avatar" varchar NOT NULL,
  10 + "video" varchar NOT NULL,
  11 + "memo" varchar NOT NULL,
  12 + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  13 + PRIMARY KEY ("id")
  14 +) COMMENT '学生表';
  15 +
  16 +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里
  17 +DELETE FROM "infra_student";
0 \ No newline at end of file 18 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/sql/sql renamed to yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/sql/sql
@@ -4,8 +4,8 @@ INSERT INTO system_menu( @@ -4,8 +4,8 @@ INSERT INTO system_menu(
4 path, icon, component, status, component_name 4 path, icon, component, status, component_name
5 ) 5 )
6 VALUES ( 6 VALUES (
7 - '用户管理', '', 2, 0, 10,  
8 - 'user', '', 'system/user/index', 0, 'SystemUser' 7 + '学生管理', '', 2, 0, 888,
  8 + 'student', '', 'infra/demo/index', 0, 'InfraStudent'
9 ); 9 );
10 10
11 -- 按钮父菜单ID 11 -- 按钮父菜单ID
@@ -18,7 +18,7 @@ INSERT INTO system_menu( @@ -18,7 +18,7 @@ INSERT INTO system_menu(
18 path, icon, component, status 18 path, icon, component, status
19 ) 19 )
20 VALUES ( 20 VALUES (
21 - '用户查询', 'system:user:query', 3, 1, @parentId, 21 + '学生查询', 'infra:student:query', 3, 1, @parentId,
22 '', '', '', 0 22 '', '', '', 0
23 ); 23 );
24 INSERT INTO system_menu( 24 INSERT INTO system_menu(
@@ -26,7 +26,7 @@ INSERT INTO system_menu( @@ -26,7 +26,7 @@ INSERT INTO system_menu(
26 path, icon, component, status 26 path, icon, component, status
27 ) 27 )
28 VALUES ( 28 VALUES (
29 - '用户创建', 'system:user:create', 3, 2, @parentId, 29 + '学生创建', 'infra:student:create', 3, 2, @parentId,
30 '', '', '', 0 30 '', '', '', 0
31 ); 31 );
32 INSERT INTO system_menu( 32 INSERT INTO system_menu(
@@ -34,7 +34,7 @@ INSERT INTO system_menu( @@ -34,7 +34,7 @@ INSERT INTO system_menu(
34 path, icon, component, status 34 path, icon, component, status
35 ) 35 )
36 VALUES ( 36 VALUES (
37 - '用户更新', 'system:user:update', 3, 3, @parentId, 37 + '学生更新', 'infra:student:update', 3, 3, @parentId,
38 '', '', '', 0 38 '', '', '', 0
39 ); 39 );
40 INSERT INTO system_menu( 40 INSERT INTO system_menu(
@@ -42,7 +42,7 @@ INSERT INTO system_menu( @@ -42,7 +42,7 @@ INSERT INTO system_menu(
42 path, icon, component, status 42 path, icon, component, status
43 ) 43 )
44 VALUES ( 44 VALUES (
45 - '用户删除', 'system:user:delete', 3, 4, @parentId, 45 + '学生删除', 'infra:student:delete', 3, 4, @parentId,
46 '', '', '', 0 46 '', '', '', 0
47 ); 47 );
48 INSERT INTO system_menu( 48 INSERT INTO system_menu(
@@ -50,6 +50,6 @@ INSERT INTO system_menu( @@ -50,6 +50,6 @@ INSERT INTO system_menu(
50 path, icon, component, status 50 path, icon, component, status
51 ) 51 )
52 VALUES ( 52 VALUES (
53 - '用户导出', 'system:user:export', 3, 5, @parentId, 53 + '学生导出', 'infra:student:export', 3, 5, @parentId,
54 '', '', '', 0 54 '', '', '', 0
55 -); 55 -);
  56 +);
56 \ No newline at end of file 57 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/ts/index 0 → 100644
  1 +import request from '@/config/axios'
  2 +
  3 +export interface StudentVO {
  4 + id: number
  5 + name: string
  6 + description: string
  7 + birthday: Date
  8 + sex: number
  9 + enabled: boolean
  10 + avatar: string
  11 + video: string
  12 + memo: string
  13 +}
  14 +
  15 +// 查询学生分页
  16 +export const getStudentPage = async (params) => {
  17 + return await request.get({ url: `/infra/student/page`, params })
  18 +}
  19 +
  20 +// 查询学生详情
  21 +export const getStudent = async (id: number) => {
  22 + return await request.get({ url: `/infra/student/get?id=` + id })
  23 +}
  24 +
  25 +// 新增学生
  26 +export const createStudent = async (data: StudentVO) => {
  27 + return await request.post({ url: `/infra/student/create`, data })
  28 +}
  29 +
  30 +// 修改学生
  31 +export const updateStudent = async (data: StudentVO) => {
  32 + return await request.put({ url: `/infra/student/update`, data })
  33 +}
  34 +
  35 +// 删除学生
  36 +export const deleteStudent = async (id: number) => {
  37 + return await request.delete({ url: `/infra/student/delete?id=` + id })
  38 +}
  39 +
  40 +// 导出学生 Excel
  41 +export const exportStudent = async (params) => {
  42 + return await request.download({ url: `/infra/student/export-excel`, params })
  43 +}
  44 +
  45 +// ==================== 子表(学生联系人) ====================
  46 +
  47 +// 获得学生联系人分页
  48 +export const getStudentContactPage = async (params) => {
  49 + return await request.get({ url: `/infra/student/student-contact/page`, params })
  50 +}
  51 +// 新增学生联系人
  52 +export const createStudentContact = async (data) => {
  53 + return await request.post({ url: `/infra/student/student-contact/create`, data })
  54 +}
  55 +
  56 +// 修改学生联系人
  57 +export const updateStudentContact = async (data) => {
  58 + return await request.put({ url: `/infra/student/student-contact/update`, data })
  59 +}
  60 +
  61 +// 删除学生联系人
  62 +export const deleteStudentContact = async (id: number) => {
  63 + return await request.delete({ url: `/infra/student/student-contact/delete?id=` + id })
  64 +}
  65 +
  66 +// 获得学生联系人
  67 +export const getStudentContact = async (id: number) => {
  68 + return await request.get({ url: `/infra/student/student-contact/get?id=` + id })
  69 +}
  70 +
  71 +// ==================== 子表(学生班主任) ====================
  72 +
  73 +// 获得学生班主任分页
  74 +export const getStudentTeacherPage = async (params) => {
  75 + return await request.get({ url: `/infra/student/student-teacher/page`, params })
  76 +}
  77 +// 新增学生班主任
  78 +export const createStudentTeacher = async (data) => {
  79 + return await request.post({ url: `/infra/student/student-teacher/create`, data })
  80 +}
  81 +
  82 +// 修改学生班主任
  83 +export const updateStudentTeacher = async (data) => {
  84 + return await request.put({ url: `/infra/student/student-teacher/update`, data })
  85 +}
  86 +
  87 +// 删除学生班主任
  88 +export const deleteStudentTeacher = async (id: number) => {
  89 + return await request.delete({ url: `/infra/student/student-teacher/delete?id=` + id })
  90 +}
  91 +
  92 +// 获得学生班主任
  93 +export const getStudentTeacher = async (id: number) => {
  94 + return await request.get({ url: `/infra/student/student-teacher/get?id=` + id })
  95 +}
0 \ No newline at end of file 96 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentContactForm 0 → 100644
  1 +<template>
  2 + <Dialog :title="dialogTitle" v-model="dialogVisible">
  3 + <el-form
  4 + ref="formRef"
  5 + :model="formData"
  6 + :rules="formRules"
  7 + label-width="100px"
  8 + v-loading="formLoading"
  9 + >
  10 + <el-form-item label="名字" prop="name">
  11 + <el-input v-model="formData.name" placeholder="请输入名字" />
  12 + </el-form-item>
  13 + <el-form-item label="简介" prop="description">
  14 + <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
  15 + </el-form-item>
  16 + <el-form-item label="出生日期" prop="birthday">
  17 + <el-date-picker
  18 + v-model="formData.birthday"
  19 + type="date"
  20 + value-format="x"
  21 + placeholder="选择出生日期"
  22 + />
  23 + </el-form-item>
  24 + <el-form-item label="性别" prop="sex">
  25 + <el-select v-model="formData.sex" placeholder="请选择性别">
  26 + <el-option
  27 + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
  28 + :key="dict.value"
  29 + :label="dict.label"
  30 + :value="dict.value"
  31 + />
  32 + </el-select>
  33 + </el-form-item>
  34 + <el-form-item label="是否有效" prop="enabled">
  35 + <el-radio-group v-model="formData.enabled">
  36 + <el-radio
  37 + v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
  38 + :key="dict.value"
  39 + :label="dict.value"
  40 + >
  41 + {{ dict.label }}
  42 + </el-radio>
  43 + </el-radio-group>
  44 + </el-form-item>
  45 + <el-form-item label="头像" prop="avatar">
  46 + <UploadImg v-model="formData.avatar" />
  47 + </el-form-item>
  48 + <el-form-item label="附件" prop="video">
  49 + <UploadFile v-model="formData.video" />
  50 + </el-form-item>
  51 + <el-form-item label="备注" prop="memo">
  52 + <Editor v-model="formData.memo" height="150px" />
  53 + </el-form-item>
  54 + </el-form>
  55 + <template #footer>
  56 + <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
  57 + <el-button @click="dialogVisible = false">取 消</el-button>
  58 + </template>
  59 + </Dialog>
  60 +</template>
  61 +<script setup lang="ts">
  62 +import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
  63 +import * as StudentApi from '@/api/infra/demo'
  64 +
  65 +const { t } = useI18n() // 国际化
  66 +const message = useMessage() // 消息弹窗
  67 +
  68 +const dialogVisible = ref(false) // 弹窗的是否展示
  69 +const dialogTitle = ref('') // 弹窗的标题
  70 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  71 +const formType = ref('') // 表单的类型:create - 新增;update - 修改
  72 +const formData = ref({
  73 + id: undefined,
  74 + studentId: undefined,
  75 + name: undefined,
  76 + description: undefined,
  77 + birthday: undefined,
  78 + sex: undefined,
  79 + enabled: undefined,
  80 + avatar: undefined,
  81 + video: undefined,
  82 + memo: undefined
  83 +})
  84 +const formRules = reactive({
  85 + studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
  86 + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
  87 + description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
  88 + birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
  89 + sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
  90 + enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
  91 + avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
  92 + memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
  93 +})
  94 +const formRef = ref() // 表单 Ref
  95 +
  96 +/** 打开弹窗 */
  97 +const open = async (type: string, id?: number, studentId: number) => {
  98 + dialogVisible.value = true
  99 + dialogTitle.value = t('action.' + type)
  100 + formType.value = type
  101 + resetForm()
  102 + formData.value.studentId = studentId
  103 + // 修改时,设置数据
  104 + if (id) {
  105 + formLoading.value = true
  106 + try {
  107 + formData.value = await StudentApi.getStudentContact(id)
  108 + } finally {
  109 + formLoading.value = false
  110 + }
  111 + }
  112 +}
  113 +defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  114 +
  115 +/** 提交表单 */
  116 +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  117 +const submitForm = async () => {
  118 + // 校验表单
  119 + await formRef.value.validate()
  120 + // 提交请求
  121 + formLoading.value = true
  122 + try {
  123 + const data = formData.value
  124 + if (formType.value === 'create') {
  125 + await StudentApi.createStudentContact(data)
  126 + message.success(t('common.createSuccess'))
  127 + } else {
  128 + await StudentApi.updateStudentContact(data)
  129 + message.success(t('common.updateSuccess'))
  130 + }
  131 + dialogVisible.value = false
  132 + // 发送操作成功的事件
  133 + emit('success')
  134 + } finally {
  135 + formLoading.value = false
  136 + }
  137 +}
  138 +
  139 +/** 重置表单 */
  140 +const resetForm = () => {
  141 + formData.value = {
  142 + id: undefined,
  143 + studentId: undefined,
  144 + name: undefined,
  145 + description: undefined,
  146 + birthday: undefined,
  147 + sex: undefined,
  148 + enabled: undefined,
  149 + avatar: undefined,
  150 + video: undefined,
  151 + memo: undefined
  152 + }
  153 + formRef.value?.resetFields()
  154 +}
  155 +</script>
0 \ No newline at end of file 156 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentContactList 0 → 100644
  1 +<template>
  2 + <!-- 列表 -->
  3 + <ContentWrap>
  4 + <el-button
  5 + type="primary"
  6 + plain
  7 + @click="openForm('create')"
  8 + v-hasPermi="['infra:student:create']"
  9 + >
  10 + <Icon icon="ep:plus" class="mr-5px" /> 新增
  11 + </el-button>
  12 + <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
  13 + <el-table-column label="编号" align="center" prop="id" />
  14 + <el-table-column label="名字" align="center" prop="name" />
  15 + <el-table-column label="简介" align="center" prop="description" />
  16 + <el-table-column
  17 + label="出生日期"
  18 + align="center"
  19 + prop="birthday"
  20 + :formatter="dateFormatter"
  21 + width="180px"
  22 + />
  23 + <el-table-column label="性别" align="center" prop="sex">
  24 + <template #default="scope">
  25 + <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
  26 + </template>
  27 + </el-table-column>
  28 + <el-table-column label="是否有效" align="center" prop="enabled">
  29 + <template #default="scope">
  30 + <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
  31 + </template>
  32 + </el-table-column>
  33 + <el-table-column label="头像" align="center" prop="avatar" />
  34 + <el-table-column label="附件" align="center" prop="video" />
  35 + <el-table-column label="备注" align="center" prop="memo" />
  36 + <el-table-column
  37 + label="创建时间"
  38 + align="center"
  39 + prop="createTime"
  40 + :formatter="dateFormatter"
  41 + width="180px"
  42 + />
  43 + <el-table-column label="操作" align="center">
  44 + <template #default="scope">
  45 + <el-button
  46 + link
  47 + type="primary"
  48 + @click="openForm('update', scope.row.id)"
  49 + v-hasPermi="['infra:student:update']"
  50 + >
  51 + 编辑
  52 + </el-button>
  53 + <el-button
  54 + link
  55 + type="danger"
  56 + @click="handleDelete(scope.row.id)"
  57 + v-hasPermi="['infra:student:delete']"
  58 + >
  59 + 删除
  60 + </el-button>
  61 + </template>
  62 + </el-table-column>
  63 + </el-table>
  64 + <!-- 分页 -->
  65 + <Pagination
  66 + :total="total"
  67 + v-model:page="queryParams.pageNo"
  68 + v-model:limit="queryParams.pageSize"
  69 + @pagination="getList"
  70 + />
  71 + </ContentWrap>
  72 + <!-- 表单弹窗:添加/修改 -->
  73 + <StudentContactForm ref="formRef" @success="getList" />
  74 +</template>
  75 +<script setup lang="ts">
  76 +import { DICT_TYPE } from '@/utils/dict'
  77 +import { dateFormatter } from '@/utils/formatTime'
  78 +import * as StudentApi from '@/api/infra/demo'
  79 +import StudentContactForm from './StudentContactForm.vue'
  80 +
  81 +const { t } = useI18n() // 国际化
  82 +const message = useMessage() // 消息弹窗
  83 +
  84 +const props = defineProps<{
  85 + studentId: undefined // 学生编号(主表的关联字段)
  86 +}>()
  87 +const loading = ref(false) // 列表的加载中
  88 +const list = ref([]) // 列表的数据
  89 +const total = ref(0) // 列表的总页数
  90 +const queryParams = reactive({
  91 + pageNo: 1,
  92 + pageSize: 10,
  93 + studentId: undefined
  94 +})
  95 +
  96 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  97 +watch(
  98 + () => props.studentId,
  99 + (val) => {
  100 + queryParams.studentId = val
  101 + handleQuery()
  102 + },
  103 + { immediate: false }
  104 +)
  105 +
  106 +/** 查询列表 */
  107 +const getList = async () => {
  108 + loading.value = true
  109 + try {
  110 + const data = await StudentApi.getStudentContactPage(queryParams)
  111 + list.value = data.list
  112 + total.value = data.total
  113 + } finally {
  114 + loading.value = false
  115 + }
  116 +}
  117 +
  118 +/** 搜索按钮操作 */
  119 +const handleQuery = () => {
  120 + queryParams.pageNo = 1
  121 + getList()
  122 +}
  123 +
  124 +/** 添加/修改操作 */
  125 +const formRef = ref()
  126 +const openForm = (type: string, id?: number) => {
  127 + if (!props.studentId) {
  128 + message.error('请选择一个学生')
  129 + return
  130 + }
  131 + formRef.value.open(type, id, props.studentId)
  132 +}
  133 +
  134 +/** 删除按钮操作 */
  135 +const handleDelete = async (id: number) => {
  136 + try {
  137 + // 删除的二次确认
  138 + await message.delConfirm()
  139 + // 发起删除
  140 + await StudentApi.deleteStudentContact(id)
  141 + message.success(t('common.delSuccess'))
  142 + // 刷新列表
  143 + await getList()
  144 + } catch {}
  145 +}
  146 +</script>
0 \ No newline at end of file 147 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/vue/form renamed to yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentForm
@@ -10,34 +10,31 @@ @@ -10,34 +10,31 @@
10 <el-form-item label="名字" prop="name"> 10 <el-form-item label="名字" prop="name">
11 <el-input v-model="formData.name" placeholder="请输入名字" /> 11 <el-input v-model="formData.name" placeholder="请输入名字" />
12 </el-form-item> 12 </el-form-item>
13 - <el-form-item label="个人简介">  
14 - <Editor v-model="formData.description" height="150px" /> 13 + <el-form-item label="简介" prop="description">
  14 + <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
15 </el-form-item> 15 </el-form-item>
16 - <el-form-item label="性别 1" prop="sex1">  
17 - <el-select v-model="formData.sex1" placeholder="请选择性别 1"> 16 + <el-form-item label="出生日期" prop="birthday">
  17 + <el-date-picker
  18 + v-model="formData.birthday"
  19 + type="date"
  20 + value-format="x"
  21 + placeholder="选择出生日期"
  22 + />
  23 + </el-form-item>
  24 + <el-form-item label="性别" prop="sex">
  25 + <el-select v-model="formData.sex" placeholder="请选择性别">
18 <el-option 26 <el-option
19 - v-for="dict in getStrDictOptions(DICT_TYPE.SYSTEM_SEX1)" 27 + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
20 :key="dict.value" 28 :key="dict.value"
21 :label="dict.label" 29 :label="dict.label"
22 :value="dict.value" 30 :value="dict.value"
23 /> 31 />
24 </el-select> 32 </el-select>
25 </el-form-item> 33 </el-form-item>
26 - <el-form-item label="性别 2" prop="sex2">  
27 - <el-checkbox-group v-model="formData.sex2">  
28 - <el-checkbox  
29 - v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_SEX2)"  
30 - :key="dict.value"  
31 - :label="dict.value"  
32 - >  
33 - {{ dict.label }}  
34 - </el-checkbox>  
35 - </el-checkbox-group>  
36 - </el-form-item>  
37 - <el-form-item label="性别 3" prop="sex3">  
38 - <el-radio-group v-model="formData.sex3"> 34 + <el-form-item label="是否有效" prop="enabled">
  35 + <el-radio-group v-model="formData.enabled">
39 <el-radio 36 <el-radio
40 - v-for="dict in getBoolDictOptions(DICT_TYPE.SYSTEM_SEX3)" 37 + v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
41 :key="dict.value" 38 :key="dict.value"
42 :label="dict.value" 39 :label="dict.value"
43 > 40 >
@@ -45,24 +42,14 @@ @@ -45,24 +42,14 @@
45 </el-radio> 42 </el-radio>
46 </el-radio-group> 43 </el-radio-group>
47 </el-form-item> 44 </el-form-item>
48 - <el-form-item label="出生日期" prop="birthday">  
49 - <el-date-picker  
50 - v-model="formData.birthday"  
51 - type="date"  
52 - value-format="x"  
53 - placeholder="选择出生日期"  
54 - /> 45 + <el-form-item label="头像" prop="avatar">
  46 + <UploadImg v-model="formData.avatar" />
55 </el-form-item> 47 </el-form-item>
56 - <el-form-item label="备注" prop="memo">  
57 - <el-input v-model="formData.memo" type="textarea" placeholder="请输入备注" /> 48 + <el-form-item label="附件" prop="video">
  49 + <UploadFile v-model="formData.video" />
58 </el-form-item> 50 </el-form-item>
59 - <el-form-item label="创建时间" prop="createTime">  
60 - <el-date-picker  
61 - v-model="formData.createTime"  
62 - type="date"  
63 - value-format="x"  
64 - placeholder="选择创建时间"  
65 - /> 51 + <el-form-item label="备注" prop="memo">
  52 + <Editor v-model="formData.memo" height="150px" />
66 </el-form-item> 53 </el-form-item>
67 </el-form> 54 </el-form>
68 <template #footer> 55 <template #footer>
@@ -72,8 +59,8 @@ @@ -72,8 +59,8 @@
72 </Dialog> 59 </Dialog>
73 </template> 60 </template>
74 <script setup lang="ts"> 61 <script setup lang="ts">
75 -import { DICT_TYPE, getStrDictOptions, getIntDictOptions, getBoolDictOptions } from '@/utils/dict'  
76 -import * as UserApi from '@/api/system/user' 62 +import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
  63 +import * as StudentApi from '@/api/infra/demo'
77 64
78 const { t } = useI18n() // 国际化 65 const { t } = useI18n() // 国际化
79 const message = useMessage() // 消息弹窗 66 const message = useMessage() // 消息弹窗
@@ -85,18 +72,23 @@ const formType = ref(&#39;&#39;) // 表单的类型:create - 新增;update - 修改 @@ -85,18 +72,23 @@ const formType = ref(&#39;&#39;) // 表单的类型:create - 新增;update - 修改
85 const formData = ref({ 72 const formData = ref({
86 id: undefined, 73 id: undefined,
87 name: undefined, 74 name: undefined,
88 - avatar: undefined,  
89 - video: undefined,  
90 description: undefined, 75 description: undefined,
91 - sex1: undefined,  
92 - sex2: [],  
93 - sex3: undefined,  
94 birthday: undefined, 76 birthday: undefined,
95 - memo: undefined,  
96 - createTime: undefined 77 + sex: undefined,
  78 + enabled: undefined,
  79 + avatar: undefined,
  80 + video: undefined,
  81 + memo: undefined
97 }) 82 })
98 const formRules = reactive({ 83 const formRules = reactive({
99 - name: [{ required: true, message: '名字不能为空', trigger: 'blur' }] 84 + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
  85 + description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
  86 + birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
  87 + sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
  88 + enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
  89 + avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
  90 + video: [{ required: true, message: '附件不能为空', trigger: 'blur' }],
  91 + memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
100 }) 92 })
101 const formRef = ref() // 表单 Ref 93 const formRef = ref() // 表单 Ref
102 94
@@ -110,7 +102,7 @@ const open = async (type: string, id?: number) =&gt; { @@ -110,7 +102,7 @@ const open = async (type: string, id?: number) =&gt; {
110 if (id) { 102 if (id) {
111 formLoading.value = true 103 formLoading.value = true
112 try { 104 try {
113 - formData.value = await UserApi.getUser(id) 105 + formData.value = await StudentApi.getStudent(id)
114 } finally { 106 } finally {
115 formLoading.value = false 107 formLoading.value = false
116 } 108 }
@@ -122,18 +114,16 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗 @@ -122,18 +114,16 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
122 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 114 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
123 const submitForm = async () => { 115 const submitForm = async () => {
124 // 校验表单 116 // 校验表单
125 - if (!formRef) return  
126 - const valid = await formRef.value.validate()  
127 - if (!valid) return 117 + await formRef.value.validate()
128 // 提交请求 118 // 提交请求
129 formLoading.value = true 119 formLoading.value = true
130 try { 120 try {
131 - const data = formData.value as unknown as UserApi.UserVO 121 + const data = formData.value as unknown as StudentApi.StudentVO
132 if (formType.value === 'create') { 122 if (formType.value === 'create') {
133 - await UserApi.createUser(data) 123 + await StudentApi.createStudent(data)
134 message.success(t('common.createSuccess')) 124 message.success(t('common.createSuccess'))
135 } else { 125 } else {
136 - await UserApi.updateUser(data) 126 + await StudentApi.updateStudent(data)
137 message.success(t('common.updateSuccess')) 127 message.success(t('common.updateSuccess'))
138 } 128 }
139 dialogVisible.value = false 129 dialogVisible.value = false
@@ -149,15 +139,13 @@ const resetForm = () =&gt; { @@ -149,15 +139,13 @@ const resetForm = () =&gt; {
149 formData.value = { 139 formData.value = {
150 id: undefined, 140 id: undefined,
151 name: undefined, 141 name: undefined,
152 - avatar: undefined,  
153 - video: undefined,  
154 description: undefined, 142 description: undefined,
155 - sex1: undefined,  
156 - sex2: [],  
157 - sex3: undefined,  
158 birthday: undefined, 143 birthday: undefined,
159 - memo: undefined,  
160 - createTime: undefined 144 + sex: undefined,
  145 + enabled: undefined,
  146 + avatar: undefined,
  147 + video: undefined,
  148 + memo: undefined
161 } 149 }
162 formRef.value?.resetFields() 150 formRef.value?.resetFields()
163 } 151 }
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentTeacherForm 0 → 100644
  1 +<template>
  2 + <Dialog :title="dialogTitle" v-model="dialogVisible">
  3 + <el-form
  4 + ref="formRef"
  5 + :model="formData"
  6 + :rules="formRules"
  7 + label-width="100px"
  8 + v-loading="formLoading"
  9 + >
  10 + <el-form-item label="名字" prop="name">
  11 + <el-input v-model="formData.name" placeholder="请输入名字" />
  12 + </el-form-item>
  13 + <el-form-item label="简介" prop="description">
  14 + <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
  15 + </el-form-item>
  16 + <el-form-item label="出生日期" prop="birthday">
  17 + <el-date-picker
  18 + v-model="formData.birthday"
  19 + type="date"
  20 + value-format="x"
  21 + placeholder="选择出生日期"
  22 + />
  23 + </el-form-item>
  24 + <el-form-item label="性别" prop="sex">
  25 + <el-select v-model="formData.sex" placeholder="请选择性别">
  26 + <el-option
  27 + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
  28 + :key="dict.value"
  29 + :label="dict.label"
  30 + :value="dict.value"
  31 + />
  32 + </el-select>
  33 + </el-form-item>
  34 + <el-form-item label="是否有效" prop="enabled">
  35 + <el-radio-group v-model="formData.enabled">
  36 + <el-radio
  37 + v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
  38 + :key="dict.value"
  39 + :label="dict.value"
  40 + >
  41 + {{ dict.label }}
  42 + </el-radio>
  43 + </el-radio-group>
  44 + </el-form-item>
  45 + <el-form-item label="头像" prop="avatar">
  46 + <UploadImg v-model="formData.avatar" />
  47 + </el-form-item>
  48 + <el-form-item label="附件" prop="video">
  49 + <UploadFile v-model="formData.video" />
  50 + </el-form-item>
  51 + <el-form-item label="备注" prop="memo">
  52 + <Editor v-model="formData.memo" height="150px" />
  53 + </el-form-item>
  54 + </el-form>
  55 + <template #footer>
  56 + <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
  57 + <el-button @click="dialogVisible = false">取 消</el-button>
  58 + </template>
  59 + </Dialog>
  60 +</template>
  61 +<script setup lang="ts">
  62 +import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
  63 +import * as StudentApi from '@/api/infra/demo'
  64 +
  65 +const { t } = useI18n() // 国际化
  66 +const message = useMessage() // 消息弹窗
  67 +
  68 +const dialogVisible = ref(false) // 弹窗的是否展示
  69 +const dialogTitle = ref('') // 弹窗的标题
  70 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  71 +const formType = ref('') // 表单的类型:create - 新增;update - 修改
  72 +const formData = ref({
  73 + id: undefined,
  74 + studentId: undefined,
  75 + name: undefined,
  76 + description: undefined,
  77 + birthday: undefined,
  78 + sex: undefined,
  79 + enabled: undefined,
  80 + avatar: undefined,
  81 + video: undefined,
  82 + memo: undefined
  83 +})
  84 +const formRules = reactive({
  85 + studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
  86 + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
  87 + description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
  88 + birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
  89 + sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
  90 + enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
  91 + avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
  92 + memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
  93 +})
  94 +const formRef = ref() // 表单 Ref
  95 +
  96 +/** 打开弹窗 */
  97 +const open = async (type: string, id?: number, studentId: number) => {
  98 + dialogVisible.value = true
  99 + dialogTitle.value = t('action.' + type)
  100 + formType.value = type
  101 + resetForm()
  102 + formData.value.studentId = studentId
  103 + // 修改时,设置数据
  104 + if (id) {
  105 + formLoading.value = true
  106 + try {
  107 + formData.value = await StudentApi.getStudentTeacher(id)
  108 + } finally {
  109 + formLoading.value = false
  110 + }
  111 + }
  112 +}
  113 +defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  114 +
  115 +/** 提交表单 */
  116 +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  117 +const submitForm = async () => {
  118 + // 校验表单
  119 + await formRef.value.validate()
  120 + // 提交请求
  121 + formLoading.value = true
  122 + try {
  123 + const data = formData.value
  124 + if (formType.value === 'create') {
  125 + await StudentApi.createStudentTeacher(data)
  126 + message.success(t('common.createSuccess'))
  127 + } else {
  128 + await StudentApi.updateStudentTeacher(data)
  129 + message.success(t('common.updateSuccess'))
  130 + }
  131 + dialogVisible.value = false
  132 + // 发送操作成功的事件
  133 + emit('success')
  134 + } finally {
  135 + formLoading.value = false
  136 + }
  137 +}
  138 +
  139 +/** 重置表单 */
  140 +const resetForm = () => {
  141 + formData.value = {
  142 + id: undefined,
  143 + studentId: undefined,
  144 + name: undefined,
  145 + description: undefined,
  146 + birthday: undefined,
  147 + sex: undefined,
  148 + enabled: undefined,
  149 + avatar: undefined,
  150 + video: undefined,
  151 + memo: undefined
  152 + }
  153 + formRef.value?.resetFields()
  154 +}
  155 +</script>
0 \ No newline at end of file 156 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentTeacherList 0 → 100644
  1 +<template>
  2 + <!-- 列表 -->
  3 + <ContentWrap>
  4 + <el-button
  5 + type="primary"
  6 + plain
  7 + @click="openForm('create')"
  8 + v-hasPermi="['infra:student:create']"
  9 + >
  10 + <Icon icon="ep:plus" class="mr-5px" /> 新增
  11 + </el-button>
  12 + <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
  13 + <el-table-column label="编号" align="center" prop="id" />
  14 + <el-table-column label="名字" align="center" prop="name" />
  15 + <el-table-column label="简介" align="center" prop="description" />
  16 + <el-table-column
  17 + label="出生日期"
  18 + align="center"
  19 + prop="birthday"
  20 + :formatter="dateFormatter"
  21 + width="180px"
  22 + />
  23 + <el-table-column label="性别" align="center" prop="sex">
  24 + <template #default="scope">
  25 + <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
  26 + </template>
  27 + </el-table-column>
  28 + <el-table-column label="是否有效" align="center" prop="enabled">
  29 + <template #default="scope">
  30 + <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
  31 + </template>
  32 + </el-table-column>
  33 + <el-table-column label="头像" align="center" prop="avatar" />
  34 + <el-table-column label="附件" align="center" prop="video" />
  35 + <el-table-column label="备注" align="center" prop="memo" />
  36 + <el-table-column
  37 + label="创建时间"
  38 + align="center"
  39 + prop="createTime"
  40 + :formatter="dateFormatter"
  41 + width="180px"
  42 + />
  43 + <el-table-column label="操作" align="center">
  44 + <template #default="scope">
  45 + <el-button
  46 + link
  47 + type="primary"
  48 + @click="openForm('update', scope.row.id)"
  49 + v-hasPermi="['infra:student:update']"
  50 + >
  51 + 编辑
  52 + </el-button>
  53 + <el-button
  54 + link
  55 + type="danger"
  56 + @click="handleDelete(scope.row.id)"
  57 + v-hasPermi="['infra:student:delete']"
  58 + >
  59 + 删除
  60 + </el-button>
  61 + </template>
  62 + </el-table-column>
  63 + </el-table>
  64 + <!-- 分页 -->
  65 + <Pagination
  66 + :total="total"
  67 + v-model:page="queryParams.pageNo"
  68 + v-model:limit="queryParams.pageSize"
  69 + @pagination="getList"
  70 + />
  71 + </ContentWrap>
  72 + <!-- 表单弹窗:添加/修改 -->
  73 + <StudentTeacherForm ref="formRef" @success="getList" />
  74 +</template>
  75 +<script setup lang="ts">
  76 +import { DICT_TYPE } from '@/utils/dict'
  77 +import { dateFormatter } from '@/utils/formatTime'
  78 +import * as StudentApi from '@/api/infra/demo'
  79 +import StudentTeacherForm from './StudentTeacherForm.vue'
  80 +
  81 +const { t } = useI18n() // 国际化
  82 +const message = useMessage() // 消息弹窗
  83 +
  84 +const props = defineProps<{
  85 + studentId: undefined // 学生编号(主表的关联字段)
  86 +}>()
  87 +const loading = ref(false) // 列表的加载中
  88 +const list = ref([]) // 列表的数据
  89 +const total = ref(0) // 列表的总页数
  90 +const queryParams = reactive({
  91 + pageNo: 1,
  92 + pageSize: 10,
  93 + studentId: undefined
  94 +})
  95 +
  96 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  97 +watch(
  98 + () => props.studentId,
  99 + (val) => {
  100 + queryParams.studentId = val
  101 + handleQuery()
  102 + },
  103 + { immediate: false }
  104 +)
  105 +
  106 +/** 查询列表 */
  107 +const getList = async () => {
  108 + loading.value = true
  109 + try {
  110 + const data = await StudentApi.getStudentTeacherPage(queryParams)
  111 + list.value = data.list
  112 + total.value = data.total
  113 + } finally {
  114 + loading.value = false
  115 + }
  116 +}
  117 +
  118 +/** 搜索按钮操作 */
  119 +const handleQuery = () => {
  120 + queryParams.pageNo = 1
  121 + getList()
  122 +}
  123 +
  124 +/** 添加/修改操作 */
  125 +const formRef = ref()
  126 +const openForm = (type: string, id?: number) => {
  127 + if (!props.studentId) {
  128 + message.error('请选择一个学生')
  129 + return
  130 + }
  131 + formRef.value.open(type, id, props.studentId)
  132 +}
  133 +
  134 +/** 删除按钮操作 */
  135 +const handleDelete = async (id: number) => {
  136 + try {
  137 + // 删除的二次确认
  138 + await message.delConfirm()
  139 + // 发起删除
  140 + await StudentApi.deleteStudentTeacher(id)
  141 + message.success(t('common.delSuccess'))
  142 + // 刷新列表
  143 + await getList()
  144 + } catch {}
  145 +}
  146 +</script>
0 \ No newline at end of file 147 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/index 0 → 100644
  1 +<template>
  2 + <ContentWrap>
  3 + <!-- 搜索工作栏 -->
  4 + <el-form
  5 + class="-mb-15px"
  6 + :model="queryParams"
  7 + ref="queryFormRef"
  8 + :inline="true"
  9 + label-width="68px"
  10 + >
  11 + <el-form-item label="名字" prop="name">
  12 + <el-input
  13 + v-model="queryParams.name"
  14 + placeholder="请输入名字"
  15 + clearable
  16 + @keyup.enter="handleQuery"
  17 + class="!w-240px"
  18 + />
  19 + </el-form-item>
  20 + <el-form-item label="出生日期" prop="birthday">
  21 + <el-date-picker
  22 + v-model="queryParams.birthday"
  23 + value-format="YYYY-MM-DD"
  24 + type="date"
  25 + placeholder="选择出生日期"
  26 + clearable
  27 + class="!w-240px"
  28 + />
  29 + </el-form-item>
  30 + <el-form-item label="性别" prop="sex">
  31 + <el-select
  32 + v-model="queryParams.sex"
  33 + placeholder="请选择性别"
  34 + clearable
  35 + class="!w-240px"
  36 + >
  37 + <el-option
  38 + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
  39 + :key="dict.value"
  40 + :label="dict.label"
  41 + :value="dict.value"
  42 + />
  43 + </el-select>
  44 + </el-form-item>
  45 + <el-form-item label="是否有效" prop="enabled">
  46 + <el-select
  47 + v-model="queryParams.enabled"
  48 + placeholder="请选择是否有效"
  49 + clearable
  50 + class="!w-240px"
  51 + >
  52 + <el-option
  53 + v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
  54 + :key="dict.value"
  55 + :label="dict.label"
  56 + :value="dict.value"
  57 + />
  58 + </el-select>
  59 + </el-form-item>
  60 + <el-form-item label="创建时间" prop="createTime">
  61 + <el-date-picker
  62 + v-model="queryParams.createTime"
  63 + value-format="YYYY-MM-DD HH:mm:ss"
  64 + type="daterange"
  65 + start-placeholder="开始日期"
  66 + end-placeholder="结束日期"
  67 + :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
  68 + class="!w-240px"
  69 + />
  70 + </el-form-item>
  71 + <el-form-item>
  72 + <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
  73 + <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
  74 + <el-button
  75 + type="primary"
  76 + plain
  77 + @click="openForm('create')"
  78 + v-hasPermi="['infra:student:create']"
  79 + >
  80 + <Icon icon="ep:plus" class="mr-5px" /> 新增
  81 + </el-button>
  82 + <el-button
  83 + type="success"
  84 + plain
  85 + @click="handleExport"
  86 + :loading="exportLoading"
  87 + v-hasPermi="['infra:student:export']"
  88 + >
  89 + <Icon icon="ep:download" class="mr-5px" /> 导出
  90 + </el-button>
  91 + </el-form-item>
  92 + </el-form>
  93 + </ContentWrap>
  94 +
  95 + <!-- 列表 -->
  96 + <ContentWrap>
  97 + <el-table
  98 + v-loading="loading"
  99 + :data="list"
  100 + :stripe="true"
  101 + :show-overflow-tooltip="true"
  102 + highlight-current-row
  103 + @current-change="handleCurrentChange"
  104 + >
  105 + <el-table-column label="编号" align="center" prop="id" />
  106 + <el-table-column label="名字" align="center" prop="name" />
  107 + <el-table-column label="简介" align="center" prop="description" />
  108 + <el-table-column
  109 + label="出生日期"
  110 + align="center"
  111 + prop="birthday"
  112 + :formatter="dateFormatter"
  113 + width="180px"
  114 + />
  115 + <el-table-column label="性别" align="center" prop="sex">
  116 + <template #default="scope">
  117 + <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
  118 + </template>
  119 + </el-table-column>
  120 + <el-table-column label="是否有效" align="center" prop="enabled">
  121 + <template #default="scope">
  122 + <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
  123 + </template>
  124 + </el-table-column>
  125 + <el-table-column label="头像" align="center" prop="avatar" />
  126 + <el-table-column label="附件" align="center" prop="video" />
  127 + <el-table-column label="备注" align="center" prop="memo" />
  128 + <el-table-column
  129 + label="创建时间"
  130 + align="center"
  131 + prop="createTime"
  132 + :formatter="dateFormatter"
  133 + width="180px"
  134 + />
  135 + <el-table-column label="操作" align="center">
  136 + <template #default="scope">
  137 + <el-button
  138 + link
  139 + type="primary"
  140 + @click="openForm('update', scope.row.id)"
  141 + v-hasPermi="['infra:student:update']"
  142 + >
  143 + 编辑
  144 + </el-button>
  145 + <el-button
  146 + link
  147 + type="danger"
  148 + @click="handleDelete(scope.row.id)"
  149 + v-hasPermi="['infra:student:delete']"
  150 + >
  151 + 删除
  152 + </el-button>
  153 + </template>
  154 + </el-table-column>
  155 + </el-table>
  156 + <!-- 分页 -->
  157 + <Pagination
  158 + :total="total"
  159 + v-model:page="queryParams.pageNo"
  160 + v-model:limit="queryParams.pageSize"
  161 + @pagination="getList"
  162 + />
  163 + </ContentWrap>
  164 +
  165 + <!-- 表单弹窗:添加/修改 -->
  166 + <StudentForm ref="formRef" @success="getList" />
  167 + <!-- 子表的列表 -->
  168 + <ContentWrap>
  169 + <el-tabs model-value="studentContact">
  170 + <el-tab-pane label="学生联系人" name="studentContact">
  171 + <StudentContactList :student-id="currentRow.id" />
  172 + </el-tab-pane>
  173 + <el-tab-pane label="学生班主任" name="studentTeacher">
  174 + <StudentTeacherList :student-id="currentRow.id" />
  175 + </el-tab-pane>
  176 + </el-tabs>
  177 + </ContentWrap>
  178 +</template>
  179 +
  180 +<script setup lang="ts">
  181 +import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
  182 +import { dateFormatter } from '@/utils/formatTime'
  183 +import download from '@/utils/download'
  184 +import * as StudentApi from '@/api/infra/demo'
  185 +import StudentForm from './StudentForm.vue'
  186 +import StudentContactList from './components/StudentContactList.vue'
  187 +import StudentTeacherList from './components/StudentTeacherList.vue'
  188 +
  189 +defineOptions({ name: 'InfraStudent' })
  190 +
  191 +const message = useMessage() // 消息弹窗
  192 +const { t } = useI18n() // 国际化
  193 +
  194 +const loading = ref(true) // 列表的加载中
  195 +const list = ref([]) // 列表的数据
  196 +const total = ref(0) // 列表的总页数
  197 +const queryParams = reactive({
  198 + pageNo: 1,
  199 + pageSize: 10,
  200 + name: null,
  201 + birthday: null,
  202 + birthday: [],
  203 + sex: null,
  204 + enabled: null,
  205 + createTime: []
  206 +})
  207 +const queryFormRef = ref() // 搜索的表单
  208 +const exportLoading = ref(false) // 导出的加载中
  209 +
  210 +/** 查询列表 */
  211 +const getList = async () => {
  212 + loading.value = true
  213 + try {
  214 + const data = await StudentApi.getStudentPage(queryParams)
  215 + list.value = data.list
  216 + total.value = data.total
  217 + } finally {
  218 + loading.value = false
  219 + }
  220 +}
  221 +
  222 +/** 搜索按钮操作 */
  223 +const handleQuery = () => {
  224 + queryParams.pageNo = 1
  225 + getList()
  226 +}
  227 +
  228 +/** 重置按钮操作 */
  229 +const resetQuery = () => {
  230 + queryFormRef.value.resetFields()
  231 + handleQuery()
  232 +}
  233 +
  234 +/** 添加/修改操作 */
  235 +const formRef = ref()
  236 +const openForm = (type: string, id?: number) => {
  237 + formRef.value.open(type, id)
  238 +}
  239 +
  240 +/** 删除按钮操作 */
  241 +const handleDelete = async (id: number) => {
  242 + try {
  243 + // 删除的二次确认
  244 + await message.delConfirm()
  245 + // 发起删除
  246 + await StudentApi.deleteStudent(id)
  247 + message.success(t('common.delSuccess'))
  248 + // 刷新列表
  249 + await getList()
  250 + } catch {}
  251 +}
  252 +
  253 +/** 导出按钮操作 */
  254 +const handleExport = async () => {
  255 + try {
  256 + // 导出的二次确认
  257 + await message.exportConfirm()
  258 + // 发起导出
  259 + exportLoading.value = true
  260 + const data = await StudentApi.exportStudent(queryParams)
  261 + download.excel(data, '学生.xls')
  262 + } catch {
  263 + } finally {
  264 + exportLoading.value = false
  265 + }
  266 +}
  267 +
  268 +/** 选中行操作 */
  269 +const currentRow = ref({}) // 选中行
  270 +const handleCurrentChange = (row) => {
  271 + currentRow.value = row
  272 +}
  273 +
  274 +/** 初始化 **/
  275 +onMounted(() => {
  276 + getList()
  277 +})
  278 +</script>
0 \ No newline at end of file 279 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserMapper_xml renamed to yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/xml/InfraStudentMapper
1 <?xml version="1.0" encoding="UTF-8"?> 1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3 -<mapper namespace="cn.iocoder.yudao.module.system.dal.mysql.user.SystemUserMapper"> 3 +<mapper namespace="cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper">
4 4
5 <!-- 5 <!--
6 一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。 6 一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/assert.json 0 → 100644
  1 +[ {
  2 + "contentPath" : "java/InfraStudentPageReqVO",
  3 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java"
  4 +}, {
  5 + "contentPath" : "java/InfraStudentRespVO",
  6 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java"
  7 +}, {
  8 + "contentPath" : "java/InfraStudentSaveReqVO",
  9 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java"
  10 +}, {
  11 + "contentPath" : "java/InfraStudentController",
  12 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java"
  13 +}, {
  14 + "contentPath" : "java/InfraStudentDO",
  15 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java"
  16 +}, {
  17 + "contentPath" : "java/InfraStudentContactDO",
  18 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java"
  19 +}, {
  20 + "contentPath" : "java/InfraStudentTeacherDO",
  21 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java"
  22 +}, {
  23 + "contentPath" : "java/InfraStudentMapper",
  24 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java"
  25 +}, {
  26 + "contentPath" : "java/InfraStudentContactMapper",
  27 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java"
  28 +}, {
  29 + "contentPath" : "java/InfraStudentTeacherMapper",
  30 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java"
  31 +}, {
  32 + "contentPath" : "xml/InfraStudentMapper",
  33 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml"
  34 +}, {
  35 + "contentPath" : "java/InfraStudentServiceImpl",
  36 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java"
  37 +}, {
  38 + "contentPath" : "java/InfraStudentService",
  39 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java"
  40 +}, {
  41 + "contentPath" : "java/InfraStudentServiceImplTest",
  42 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java"
  43 +}, {
  44 + "contentPath" : "java/ErrorCodeConstants_手动操作",
  45 + "filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java"
  46 +}, {
  47 + "contentPath" : "sql/sql",
  48 + "filePath" : "sql/sql.sql"
  49 +}, {
  50 + "contentPath" : "sql/h2",
  51 + "filePath" : "sql/h2.sql"
  52 +}, {
  53 + "contentPath" : "vue/index",
  54 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue"
  55 +}, {
  56 + "contentPath" : "vue/StudentForm",
  57 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/StudentForm.vue"
  58 +}, {
  59 + "contentPath" : "vue/StudentContactForm",
  60 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactForm.vue"
  61 +}, {
  62 + "contentPath" : "vue/StudentTeacherForm",
  63 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherForm.vue"
  64 +}, {
  65 + "contentPath" : "vue/StudentContactList",
  66 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactList.vue"
  67 +}, {
  68 + "contentPath" : "vue/StudentTeacherList",
  69 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherList.vue"
  70 +}, {
  71 + "contentPath" : "ts/index",
  72 + "filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts"
  73 +} ]
0 \ No newline at end of file 74 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/ErrorCodeConstants_手动操作 0 → 100644
  1 +// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!!
  2 +// ========== 学生 TODO 补充编号 ==========
  3 +ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在");
0 \ No newline at end of file 4 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentContactDO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import java.time.LocalDateTime;
  6 +import java.time.LocalDateTime;
  7 +import com.baomidou.mybatisplus.annotation.*;
  8 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  9 +
  10 +/**
  11 + * 学生联系人 DO
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@TableName("infra_student_contact")
  16 +@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class InfraStudentContactDO extends BaseDO {
  24 +
  25 + /**
  26 + * 编号
  27 + */
  28 + @TableId
  29 + private Long id;
  30 + /**
  31 + * 学生编号
  32 + */
  33 + private Long studentId;
  34 + /**
  35 + * 名字
  36 + */
  37 + private String name;
  38 + /**
  39 + * 简介
  40 + */
  41 + private String description;
  42 + /**
  43 + * 出生日期
  44 + */
  45 + private LocalDateTime birthday;
  46 + /**
  47 + * 性别
  48 + *
  49 + * 枚举 {@link TODO system_user_sex 对应的类}
  50 + */
  51 + private Integer sex;
  52 + /**
  53 + * 是否有效
  54 + *
  55 + * 枚举 {@link TODO infra_boolean_string 对应的类}
  56 + */
  57 + private Boolean enabled;
  58 + /**
  59 + * 头像
  60 + */
  61 + private String avatar;
  62 + /**
  63 + * 附件
  64 + */
  65 + private String video;
  66 + /**
  67 + * 备注
  68 + */
  69 + private String memo;
  70 +
  71 +}
0 \ No newline at end of file 72 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentContactMapper 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.mysql.demo;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  8 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  9 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  10 +import org.apache.ibatis.annotations.Mapper;
  11 +
  12 +/**
  13 + * 学生联系人 Mapper
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Mapper
  18 +public interface InfraStudentContactMapper extends BaseMapperX<InfraStudentContactDO> {
  19 +
  20 + default List<InfraStudentContactDO> selectListByStudentId(Long studentId) {
  21 + return selectList(InfraStudentContactDO::getStudentId, studentId);
  22 + }
  23 +
  24 + default int deleteByStudentId(Long studentId) {
  25 + return delete(InfraStudentContactDO::getStudentId, studentId);
  26 + }
  27 +
  28 +}
0 \ No newline at end of file 29 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentController 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.controller.admin.demo;
  2 +
  3 +import org.springframework.web.bind.annotation.*;
  4 +import javax.annotation.Resource;
  5 +import org.springframework.validation.annotation.Validated;
  6 +import org.springframework.security.access.prepost.PreAuthorize;
  7 +import io.swagger.v3.oas.annotations.tags.Tag;
  8 +import io.swagger.v3.oas.annotations.Parameter;
  9 +import io.swagger.v3.oas.annotations.Operation;
  10 +
  11 +import javax.validation.constraints.*;
  12 +import javax.validation.*;
  13 +import javax.servlet.http.*;
  14 +import java.util.*;
  15 +import java.io.IOException;
  16 +
  17 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  18 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  19 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  20 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  21 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  22 +
  23 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  24 +
  25 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
  26 +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
  27 +
  28 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  29 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  30 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  31 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  32 +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService;
  33 +
  34 +@Tag(name = "管理后台 - 学生")
  35 +@RestController
  36 +@RequestMapping("/infra/student")
  37 +@Validated
  38 +public class InfraStudentController {
  39 +
  40 + @Resource
  41 + private InfraStudentService studentService;
  42 +
  43 + @PostMapping("/create")
  44 + @Operation(summary = "创建学生")
  45 + @PreAuthorize("@ss.hasPermission('infra:student:create')")
  46 + public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) {
  47 + return success(studentService.createStudent(createReqVO));
  48 + }
  49 +
  50 + @PutMapping("/update")
  51 + @Operation(summary = "更新学生")
  52 + @PreAuthorize("@ss.hasPermission('infra:student:update')")
  53 + public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) {
  54 + studentService.updateStudent(updateReqVO);
  55 + return success(true);
  56 + }
  57 +
  58 + @DeleteMapping("/delete")
  59 + @Operation(summary = "删除学生")
  60 + @Parameter(name = "id", description = "编号", required = true)
  61 + @PreAuthorize("@ss.hasPermission('infra:student:delete')")
  62 + public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) {
  63 + studentService.deleteStudent(id);
  64 + return success(true);
  65 + }
  66 +
  67 + @GetMapping("/get")
  68 + @Operation(summary = "获得学生")
  69 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  70 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  71 + public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) {
  72 + InfraStudentDO student = studentService.getStudent(id);
  73 + return success(BeanUtils.toBean(student, InfraStudentRespVO.class));
  74 + }
  75 +
  76 + @GetMapping("/page")
  77 + @Operation(summary = "获得学生分页")
  78 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  79 + public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) {
  80 + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO);
  81 + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class));
  82 + }
  83 +
  84 + @GetMapping("/export-excel")
  85 + @Operation(summary = "导出学生 Excel")
  86 + @PreAuthorize("@ss.hasPermission('infra:student:export')")
  87 + @OperateLog(type = EXPORT)
  88 + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO,
  89 + HttpServletResponse response) throws IOException {
  90 + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
  91 + List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList();
  92 + // 导出 Excel
  93 + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class,
  94 + BeanUtils.toBean(list, InfraStudentRespVO.class));
  95 + }
  96 +
  97 + // ==================== 子表(学生联系人) ====================
  98 +
  99 + @GetMapping("/student-contact/list-by-student-id")
  100 + @Operation(summary = "获得学生联系人列表")
  101 + @Parameter(name = "studentId", description = "学生编号")
  102 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  103 + public CommonResult<List<InfraStudentContactDO>> getStudentContactListByStudentId(@RequestParam("studentId") Long studentId) {
  104 + return success(studentService.getStudentContactListByStudentId(studentId));
  105 + }
  106 +
  107 + // ==================== 子表(学生班主任) ====================
  108 +
  109 + @GetMapping("/student-teacher/get-by-student-id")
  110 + @Operation(summary = "获得学生班主任")
  111 + @Parameter(name = "studentId", description = "学生编号")
  112 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  113 + public CommonResult<InfraStudentTeacherDO> getStudentTeacherByStudentId(@RequestParam("studentId") Long studentId) {
  114 + return success(studentService.getStudentTeacherByStudentId(studentId));
  115 + }
  116 +
  117 +}
0 \ No newline at end of file 118 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentDO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import java.time.LocalDateTime;
  6 +import java.time.LocalDateTime;
  7 +import com.baomidou.mybatisplus.annotation.*;
  8 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  9 +
  10 +/**
  11 + * 学生 DO
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@TableName("infra_student")
  16 +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class InfraStudentDO extends BaseDO {
  24 +
  25 + /**
  26 + * 编号
  27 + */
  28 + @TableId
  29 + private Long id;
  30 + /**
  31 + * 名字
  32 + */
  33 + private String name;
  34 + /**
  35 + * 简介
  36 + */
  37 + private String description;
  38 + /**
  39 + * 出生日期
  40 + */
  41 + private LocalDateTime birthday;
  42 + /**
  43 + * 性别
  44 + *
  45 + * 枚举 {@link TODO system_user_sex 对应的类}
  46 + */
  47 + private Integer sex;
  48 + /**
  49 + * 是否有效
  50 + *
  51 + * 枚举 {@link TODO infra_boolean_string 对应的类}
  52 + */
  53 + private Boolean enabled;
  54 + /**
  55 + * 头像
  56 + */
  57 + private String avatar;
  58 + /**
  59 + * 附件
  60 + */
  61 + private String video;
  62 + /**
  63 + * 备注
  64 + */
  65 + private String memo;
  66 +
  67 +}
0 \ No newline at end of file 68 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentMapper 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.mysql.demo;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  7 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  8 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  9 +import org.apache.ibatis.annotations.Mapper;
  10 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  11 +
  12 +/**
  13 + * 学生 Mapper
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Mapper
  18 +public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> {
  19 +
  20 + default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) {
  21 + return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>()
  22 + .likeIfPresent(InfraStudentDO::getName, reqVO.getName())
  23 + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday())
  24 + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex())
  25 + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled())
  26 + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime())
  27 + .orderByDesc(InfraStudentDO::getId));
  28 + }
  29 +
  30 +}
0 \ No newline at end of file 31 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserExportReqVO renamed to yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentPageReqVO
1 -package cn.iocoder.yudao.module.system.controller.admin.user.vo; 1 +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
2 2
3 import lombok.*; 3 import lombok.*;
4 import java.util.*; 4 import java.util.*;
5 import io.swagger.v3.oas.annotations.media.Schema; 5 import io.swagger.v3.oas.annotations.media.Schema;
6 import cn.iocoder.yudao.framework.common.pojo.PageParam; 6 import cn.iocoder.yudao.framework.common.pojo.PageParam;
7 -import java.time.LocalDateTime;  
8 import org.springframework.format.annotation.DateTimeFormat; 7 import org.springframework.format.annotation.DateTimeFormat;
  8 +import java.time.LocalDateTime;
9 9
10 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 10 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
11 11
12 -@Schema(description = "管理后台 - 用户 Excel 导出 Request VO,参数和 SystemUserPageReqVO 是一致的") 12 +@Schema(description = "管理后台 - 学生分页 Request VO")
13 @Data 13 @Data
14 -public class SystemUserExportReqVO { 14 +@EqualsAndHashCode(callSuper = true)
  15 +@ToString(callSuper = true)
  16 +public class InfraStudentPageReqVO extends PageParam {
15 17
16 @Schema(description = "名字", example = "芋头") 18 @Schema(description = "名字", example = "芋头")
17 private String name; 19 private String name;
18 20
19 - @Schema(description = "性别 1", example = "男")  
20 - private String sex1;  
21 -  
22 - @Schema(description = "性别 2", example = "1")  
23 - private Integer sex2;  
24 -  
25 - @Schema(description = "性别 3", example = "true")  
26 - private Boolean sex3;  
27 -  
28 @Schema(description = "出生日期") 21 @Schema(description = "出生日期")
29 private LocalDateTime birthday; 22 private LocalDateTime birthday;
30 23
  24 + @Schema(description = "性别", example = "1")
  25 + private Integer sex;
  26 +
  27 + @Schema(description = "是否有效", example = "true")
  28 + private Boolean enabled;
  29 +
31 @Schema(description = "创建时间") 30 @Schema(description = "创建时间")
32 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 31 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
33 private LocalDateTime[] createTime; 32 private LocalDateTime[] createTime;
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentRespVO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import java.util.*;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +import java.time.LocalDateTime;
  9 +import com.alibaba.excel.annotation.*;
  10 +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
  11 +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
  12 +
  13 +@Schema(description = "管理后台 - 学生 Response VO")
  14 +@Data
  15 +@ExcelIgnoreUnannotated
  16 +public class InfraStudentRespVO {
  17 +
  18 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  19 + @ExcelProperty("编号")
  20 + private Long id;
  21 +
  22 + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
  23 + @ExcelProperty("名字")
  24 + private String name;
  25 +
  26 + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
  27 + @ExcelProperty("简介")
  28 + private String description;
  29 +
  30 + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
  31 + @ExcelProperty("出生日期")
  32 + private LocalDateTime birthday;
  33 +
  34 + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  35 + @ExcelProperty(value = "性别", converter = DictConvert.class)
  36 + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
  37 + private Integer sex;
  38 +
  39 + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  40 + @ExcelProperty(value = "是否有效", converter = DictConvert.class)
  41 + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
  42 + private Boolean enabled;
  43 +
  44 + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
  45 + @ExcelProperty("头像")
  46 + private String avatar;
  47 +
  48 + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
  49 + @ExcelProperty("附件")
  50 + private String video;
  51 +
  52 + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
  53 + @ExcelProperty("备注")
  54 + private String memo;
  55 +
  56 + @Schema(description = "创建时间")
  57 + @ExcelProperty("创建时间")
  58 + private LocalDateTime createTime;
  59 +
  60 +}
0 \ No newline at end of file 61 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentSaveReqVO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import javax.validation.constraints.*;
  7 +import java.util.*;
  8 +import org.springframework.format.annotation.DateTimeFormat;
  9 +import java.time.LocalDateTime;
  10 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  11 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  12 +
  13 +@Schema(description = "管理后台 - 学生新增/修改 Request VO")
  14 +@Data
  15 +public class InfraStudentSaveReqVO {
  16 +
  17 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  18 + private Long id;
  19 +
  20 + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
  21 + @NotEmpty(message = "名字不能为空")
  22 + private String name;
  23 +
  24 + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
  25 + @NotEmpty(message = "简介不能为空")
  26 + private String description;
  27 +
  28 + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
  29 + @NotNull(message = "出生日期不能为空")
  30 + private LocalDateTime birthday;
  31 +
  32 + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  33 + @NotNull(message = "性别不能为空")
  34 + private Integer sex;
  35 +
  36 + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  37 + @NotNull(message = "是否有效不能为空")
  38 + private Boolean enabled;
  39 +
  40 + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
  41 + @NotEmpty(message = "头像不能为空")
  42 + private String avatar;
  43 +
  44 + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
  45 + @NotEmpty(message = "附件不能为空")
  46 + private String video;
  47 +
  48 + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
  49 + @NotEmpty(message = "备注不能为空")
  50 + private String memo;
  51 +
  52 + @Schema(description = "学生联系人列表")
  53 + private List<InfraStudentContactDO> studentContacts;
  54 +
  55 + @Schema(description = "学生班主任")
  56 + private InfraStudentTeacherDO studentTeacher;
  57 +
  58 +}
0 \ No newline at end of file 59 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/java/SystemUserService renamed to yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentService
1 -package cn.iocoder.yudao.module.system.service.user; 1 +package cn.iocoder.yudao.module.infra.service.demo;
2 2
3 import java.util.*; 3 import java.util.*;
4 import javax.validation.*; 4 import javax.validation.*;
5 -import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;  
6 -import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO; 5 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  6 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  7 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  8 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 9 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  10 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
8 11
9 /** 12 /**
10 - * 用户 Service 接口 13 + * 学生 Service 接口
11 * 14 *
12 * @author 芋道源码 15 * @author 芋道源码
13 */ 16 */
14 -public interface SystemUserService { 17 +public interface InfraStudentService {
15 18
16 /** 19 /**
17 - * 创建用户 20 + * 创建学生
18 * 21 *
19 * @param createReqVO 创建信息 22 * @param createReqVO 创建信息
20 * @return 编号 23 * @return 编号
21 */ 24 */
22 - Long createUser(@Valid SystemUserCreateReqVO createReqVO); 25 + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO);
23 26
24 /** 27 /**
25 - * 更新用户 28 + * 更新学生
26 * 29 *
27 * @param updateReqVO 更新信息 30 * @param updateReqVO 更新信息
28 */ 31 */
29 - void updateUser(@Valid SystemUserUpdateReqVO updateReqVO); 32 + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO);
30 33
31 /** 34 /**
32 - * 删除用户 35 + * 删除学生
33 * 36 *
34 * @param id 编号 37 * @param id 编号
35 */ 38 */
36 - void deleteUser(Long id); 39 + void deleteStudent(Long id);
37 40
38 /** 41 /**
39 - * 获得用户 42 + * 获得学生
40 * 43 *
41 * @param id 编号 44 * @param id 编号
42 - * @return 用户 45 + * @return 学生
43 */ 46 */
44 - SystemUserDO getUser(Long id); 47 + InfraStudentDO getStudent(Long id);
45 48
46 /** 49 /**
47 - * 获得用户列表 50 + * 获得学生分页
48 * 51 *
49 - * @param ids 编号  
50 - * @return 用户列表 52 + * @param pageReqVO 分页查询
  53 + * @return 学生分页
51 */ 54 */
52 - List<SystemUserDO> getUserList(Collection<Long> ids); 55 + PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO);
  56 +
  57 + // ==================== 子表(学生联系人) ====================
53 58
54 /** 59 /**
55 - * 获得用户分页 60 + * 获得学生联系人列表
56 * 61 *
57 - * @param pageReqVO 分页查询  
58 - * @return 用户分页 62 + * @param studentId 学生编号
  63 + * @return 学生联系人列表
59 */ 64 */
60 - PageResult<SystemUserDO> getUserPage(SystemUserPageReqVO pageReqVO); 65 + List<InfraStudentContactDO> getStudentContactListByStudentId(Long studentId);
  66 +
  67 + // ==================== 子表(学生班主任) ====================
61 68
62 /** 69 /**
63 - * 获得用户列表, 用于 Excel 导出 70 + * 获得学生班主任
64 * 71 *
65 - * @param exportReqVO 查询条件  
66 - * @return 用户列表 72 + * @param studentId 学生编号
  73 + * @return 学生班主任
67 */ 74 */
68 - List<SystemUserDO> getUserList(SystemUserExportReqVO exportReqVO); 75 + InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId);
69 76
70 } 77 }
71 \ No newline at end of file 78 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentServiceImpl 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.service.demo;
  2 +
  3 +import org.springframework.stereotype.Service;
  4 +import javax.annotation.Resource;
  5 +import org.springframework.validation.annotation.Validated;
  6 +import org.springframework.transaction.annotation.Transactional;
  7 +
  8 +import java.util.*;
  9 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  10 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  11 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  12 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  13 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  14 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  15 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  16 +
  17 +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
  18 +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper;
  19 +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper;
  20 +
  21 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  22 +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
  23 +
  24 +/**
  25 + * 学生 Service 实现类
  26 + *
  27 + * @author 芋道源码
  28 + */
  29 +@Service
  30 +@Validated
  31 +public class InfraStudentServiceImpl implements InfraStudentService {
  32 +
  33 + @Resource
  34 + private InfraStudentMapper studentMapper;
  35 + @Resource
  36 + private InfraStudentContactMapper studentContactMapper;
  37 + @Resource
  38 + private InfraStudentTeacherMapper studentTeacherMapper;
  39 +
  40 + @Override
  41 + @Transactional(rollbackFor = Exception.class)
  42 + public Long createStudent(InfraStudentSaveReqVO createReqVO) {
  43 + // 插入
  44 + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class);
  45 + studentMapper.insert(student);
  46 +
  47 + // 插入子表
  48 + createStudentContactList(student.getId(), createReqVO.getStudentContacts());
  49 + createStudentTeacher(student.getId(), createReqVO.getStudentTeacher());
  50 + // 返回
  51 + return student.getId();
  52 + }
  53 +
  54 + @Override
  55 + @Transactional(rollbackFor = Exception.class)
  56 + public void updateStudent(InfraStudentSaveReqVO updateReqVO) {
  57 + // 校验存在
  58 + validateStudentExists(updateReqVO.getId());
  59 + // 更新
  60 + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class);
  61 + studentMapper.updateById(updateObj);
  62 +
  63 + // 更新子表
  64 + updateStudentContactList(updateReqVO.getId(), updateReqVO.getStudentContacts());
  65 + updateStudentTeacher(updateReqVO.getId(), updateReqVO.getStudentTeacher());
  66 + }
  67 +
  68 + @Override
  69 + @Transactional(rollbackFor = Exception.class)
  70 + public void deleteStudent(Long id) {
  71 + // 校验存在
  72 + validateStudentExists(id);
  73 + // 删除
  74 + studentMapper.deleteById(id);
  75 +
  76 + // 删除子表
  77 + deleteStudentContactByStudentId(id);
  78 + deleteStudentTeacherByStudentId(id);
  79 + }
  80 +
  81 + private void validateStudentExists(Long id) {
  82 + if (studentMapper.selectById(id) == null) {
  83 + throw exception(STUDENT_NOT_EXISTS);
  84 + }
  85 + }
  86 +
  87 + @Override
  88 + public InfraStudentDO getStudent(Long id) {
  89 + return studentMapper.selectById(id);
  90 + }
  91 +
  92 + @Override
  93 + public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) {
  94 + return studentMapper.selectPage(pageReqVO);
  95 + }
  96 +
  97 + // ==================== 子表(学生联系人) ====================
  98 +
  99 + @Override
  100 + public List<InfraStudentContactDO> getStudentContactListByStudentId(Long studentId) {
  101 + return studentContactMapper.selectListByStudentId(studentId);
  102 + }
  103 +
  104 + private void createStudentContactList(Long studentId, List<InfraStudentContactDO> list) {
  105 + list.forEach(o -> o.setStudentId(studentId));
  106 + studentContactMapper.insertBatch(list);
  107 + }
  108 +
  109 + private void updateStudentContactList(Long studentId, List<InfraStudentContactDO> list) {
  110 + deleteStudentContactByStudentId(studentId);
  111 + list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新
  112 + createStudentContactList(studentId, list);
  113 + }
  114 +
  115 + private void deleteStudentContactByStudentId(Long studentId) {
  116 + studentContactMapper.deleteByStudentId(studentId);
  117 + }
  118 +
  119 + // ==================== 子表(学生班主任) ====================
  120 +
  121 + @Override
  122 + public InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId) {
  123 + return studentTeacherMapper.selectByStudentId(studentId);
  124 + }
  125 +
  126 + private void createStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) {
  127 + if (studentTeacher == null) {
  128 + return;
  129 + }
  130 + studentTeacher.setStudentId(studentId);
  131 + studentTeacherMapper.insert(studentTeacher);
  132 + }
  133 +
  134 + private void updateStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) {
  135 + if (studentTeacher == null) {
  136 + return;
  137 + }
  138 + studentTeacher.setStudentId(studentId);
  139 + studentTeacher.setUpdater(null).setUpdateTime(null); // 解决更新情况下:updateTime 不更新
  140 + studentTeacherMapper.insertOrUpdate(studentTeacher);
  141 + }
  142 +
  143 + private void deleteStudentTeacherByStudentId(Long studentId) {
  144 + studentTeacherMapper.deleteByStudentId(studentId);
  145 + }
  146 +
  147 +}
0 \ No newline at end of file 148 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentServiceImplTest 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.service.demo;
  2 +
  3 +import org.junit.jupiter.api.Disabled;
  4 +import org.junit.jupiter.api.Test;
  5 +import org.springframework.boot.test.mock.mockito.MockBean;
  6 +
  7 +import javax.annotation.Resource;
  8 +
  9 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  10 +
  11 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  12 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  13 +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
  14 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  15 +
  16 +import javax.annotation.Resource;
  17 +import org.springframework.context.annotation.Import;
  18 +import java.util.*;
  19 +import java.time.LocalDateTime;
  20 +
  21 +import static cn.hutool.core.util.RandomUtil.*;
  22 +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
  23 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
  24 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
  25 +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
  26 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
  27 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
  28 +import static org.junit.jupiter.api.Assertions.*;
  29 +import static org.mockito.Mockito.*;
  30 +
  31 +/**
  32 + * {@link InfraStudentServiceImpl} 的单元测试类
  33 + *
  34 + * @author 芋道源码
  35 + */
  36 +@Import(InfraStudentServiceImpl.class)
  37 +public class InfraStudentServiceImplTest extends BaseDbUnitTest {
  38 +
  39 + @Resource
  40 + private InfraStudentServiceImpl studentService;
  41 +
  42 + @Resource
  43 + private InfraStudentMapper studentMapper;
  44 +
  45 + @Test
  46 + public void testCreateStudent_success() {
  47 + // 准备参数
  48 + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null);
  49 +
  50 + // 调用
  51 + Long studentId = studentService.createStudent(createReqVO);
  52 + // 断言
  53 + assertNotNull(studentId);
  54 + // 校验记录的属性是否正确
  55 + InfraStudentDO student = studentMapper.selectById(studentId);
  56 + assertPojoEquals(createReqVO, student, "id");
  57 + }
  58 +
  59 + @Test
  60 + public void testUpdateStudent_success() {
  61 + // mock 数据
  62 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
  63 + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
  64 + // 准备参数
  65 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> {
  66 + o.setId(dbStudent.getId()); // 设置更新的 ID
  67 + });
  68 +
  69 + // 调用
  70 + studentService.updateStudent(updateReqVO);
  71 + // 校验是否更新正确
  72 + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的
  73 + assertPojoEquals(updateReqVO, student);
  74 + }
  75 +
  76 + @Test
  77 + public void testUpdateStudent_notExists() {
  78 + // 准备参数
  79 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class);
  80 +
  81 + // 调用, 并断言异常
  82 + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS);
  83 + }
  84 +
  85 + @Test
  86 + public void testDeleteStudent_success() {
  87 + // mock 数据
  88 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
  89 + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
  90 + // 准备参数
  91 + Long id = dbStudent.getId();
  92 +
  93 + // 调用
  94 + studentService.deleteStudent(id);
  95 + // 校验数据不存在了
  96 + assertNull(studentMapper.selectById(id));
  97 + }
  98 +
  99 + @Test
  100 + public void testDeleteStudent_notExists() {
  101 + // 准备参数
  102 + Long id = randomLongId();
  103 +
  104 + // 调用, 并断言异常
  105 + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS);
  106 + }
  107 +
  108 + @Test
  109 + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
  110 + public void testGetStudentPage() {
  111 + // mock 数据
  112 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到
  113 + o.setName(null);
  114 + o.setBirthday(null);
  115 + o.setSex(null);
  116 + o.setEnabled(null);
  117 + o.setCreateTime(null);
  118 + });
  119 + studentMapper.insert(dbStudent);
  120 + // 测试 name 不匹配
  121 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null)));
  122 + // 测试 birthday 不匹配
  123 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null)));
  124 + // 测试 sex 不匹配
  125 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null)));
  126 + // 测试 enabled 不匹配
  127 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null)));
  128 + // 测试 createTime 不匹配
  129 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null)));
  130 + // 准备参数
  131 + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO();
  132 + reqVO.setName(null);
  133 + reqVO.setBirthday(null);
  134 + reqVO.setSex(null);
  135 + reqVO.setEnabled(null);
  136 + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
  137 +
  138 + // 调用
  139 + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(reqVO);
  140 + // 断言
  141 + assertEquals(1, pageResult.getTotal());
  142 + assertEquals(1, pageResult.getList().size());
  143 + assertPojoEquals(dbStudent, pageResult.getList().get(0));
  144 + }
  145 +
  146 +}
0 \ No newline at end of file 147 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentTeacherDO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import java.time.LocalDateTime;
  6 +import java.time.LocalDateTime;
  7 +import com.baomidou.mybatisplus.annotation.*;
  8 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  9 +
  10 +/**
  11 + * 学生班主任 DO
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@TableName("infra_student_teacher")
  16 +@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class InfraStudentTeacherDO extends BaseDO {
  24 +
  25 + /**
  26 + * 编号
  27 + */
  28 + @TableId
  29 + private Long id;
  30 + /**
  31 + * 学生编号
  32 + */
  33 + private Long studentId;
  34 + /**
  35 + * 名字
  36 + */
  37 + private String name;
  38 + /**
  39 + * 简介
  40 + */
  41 + private String description;
  42 + /**
  43 + * 出生日期
  44 + */
  45 + private LocalDateTime birthday;
  46 + /**
  47 + * 性别
  48 + *
  49 + * 枚举 {@link TODO system_user_sex 对应的类}
  50 + */
  51 + private Integer sex;
  52 + /**
  53 + * 是否有效
  54 + *
  55 + * 枚举 {@link TODO infra_boolean_string 对应的类}
  56 + */
  57 + private Boolean enabled;
  58 + /**
  59 + * 头像
  60 + */
  61 + private String avatar;
  62 + /**
  63 + * 附件
  64 + */
  65 + private String video;
  66 + /**
  67 + * 备注
  68 + */
  69 + private String memo;
  70 +
  71 +}
0 \ No newline at end of file 72 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentTeacherMapper 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.mysql.demo;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  8 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  9 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  10 +import org.apache.ibatis.annotations.Mapper;
  11 +
  12 +/**
  13 + * 学生班主任 Mapper
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Mapper
  18 +public interface InfraStudentTeacherMapper extends BaseMapperX<InfraStudentTeacherDO> {
  19 +
  20 + default InfraStudentTeacherDO selectByStudentId(Long studentId) {
  21 + return selectOne(InfraStudentTeacherDO::getStudentId, studentId);
  22 + }
  23 +
  24 + default int deleteByStudentId(Long studentId) {
  25 + return delete(InfraStudentTeacherDO::getStudentId, studentId);
  26 + }
  27 +
  28 +}
0 \ No newline at end of file 29 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/sql/h2 0 → 100644
  1 +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里
  2 +CREATE TABLE IF NOT EXISTS "infra_student" (
  3 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  4 + "name" varchar NOT NULL,
  5 + "description" varchar NOT NULL,
  6 + "birthday" varchar NOT NULL,
  7 + "sex" int NOT NULL,
  8 + "enabled" bit NOT NULL,
  9 + "avatar" varchar NOT NULL,
  10 + "video" varchar NOT NULL,
  11 + "memo" varchar NOT NULL,
  12 + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  13 + PRIMARY KEY ("id")
  14 +) COMMENT '学生表';
  15 +
  16 +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里
  17 +DELETE FROM "infra_student";
0 \ No newline at end of file 18 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/sql/sql 0 → 100644
  1 +-- 菜单 SQL
  2 +INSERT INTO system_menu(
  3 + name, permission, type, sort, parent_id,
  4 + path, icon, component, status, component_name
  5 +)
  6 +VALUES (
  7 + '学生管理', '', 2, 0, 888,
  8 + 'student', '', 'infra/demo/index', 0, 'InfraStudent'
  9 +);
  10 +
  11 +-- 按钮父菜单ID
  12 +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
  13 +SELECT @parentId := LAST_INSERT_ID();
  14 +
  15 +-- 按钮 SQL
  16 +INSERT INTO system_menu(
  17 + name, permission, type, sort, parent_id,
  18 + path, icon, component, status
  19 +)
  20 +VALUES (
  21 + '学生查询', 'infra:student:query', 3, 1, @parentId,
  22 + '', '', '', 0
  23 +);
  24 +INSERT INTO system_menu(
  25 + name, permission, type, sort, parent_id,
  26 + path, icon, component, status
  27 +)
  28 +VALUES (
  29 + '学生创建', 'infra:student:create', 3, 2, @parentId,
  30 + '', '', '', 0
  31 +);
  32 +INSERT INTO system_menu(
  33 + name, permission, type, sort, parent_id,
  34 + path, icon, component, status
  35 +)
  36 +VALUES (
  37 + '学生更新', 'infra:student:update', 3, 3, @parentId,
  38 + '', '', '', 0
  39 +);
  40 +INSERT INTO system_menu(
  41 + name, permission, type, sort, parent_id,
  42 + path, icon, component, status
  43 +)
  44 +VALUES (
  45 + '学生删除', 'infra:student:delete', 3, 4, @parentId,
  46 + '', '', '', 0
  47 +);
  48 +INSERT INTO system_menu(
  49 + name, permission, type, sort, parent_id,
  50 + path, icon, component, status
  51 +)
  52 +VALUES (
  53 + '学生导出', 'infra:student:export', 3, 5, @parentId,
  54 + '', '', '', 0
  55 +);
0 \ No newline at end of file 56 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/ts/index 0 → 100644
  1 +import request from '@/config/axios'
  2 +
  3 +export interface StudentVO {
  4 + id: number
  5 + name: string
  6 + description: string
  7 + birthday: Date
  8 + sex: number
  9 + enabled: boolean
  10 + avatar: string
  11 + video: string
  12 + memo: string
  13 +}
  14 +
  15 +// 查询学生分页
  16 +export const getStudentPage = async (params) => {
  17 + return await request.get({ url: `/infra/student/page`, params })
  18 +}
  19 +
  20 +// 查询学生详情
  21 +export const getStudent = async (id: number) => {
  22 + return await request.get({ url: `/infra/student/get?id=` + id })
  23 +}
  24 +
  25 +// 新增学生
  26 +export const createStudent = async (data: StudentVO) => {
  27 + return await request.post({ url: `/infra/student/create`, data })
  28 +}
  29 +
  30 +// 修改学生
  31 +export const updateStudent = async (data: StudentVO) => {
  32 + return await request.put({ url: `/infra/student/update`, data })
  33 +}
  34 +
  35 +// 删除学生
  36 +export const deleteStudent = async (id: number) => {
  37 + return await request.delete({ url: `/infra/student/delete?id=` + id })
  38 +}
  39 +
  40 +// 导出学生 Excel
  41 +export const exportStudent = async (params) => {
  42 + return await request.download({ url: `/infra/student/export-excel`, params })
  43 +}
  44 +
  45 +// ==================== 子表(学生联系人) ====================
  46 +
  47 +// 获得学生联系人列表
  48 +export const getStudentContactListByStudentId = async (studentId) => {
  49 + return await request.get({ url: `/infra/student/student-contact/list-by-student-id?studentId=` + studentId })
  50 +}
  51 +
  52 +// ==================== 子表(学生班主任) ====================
  53 +
  54 +// 获得学生班主任
  55 +export const getStudentTeacherByStudentId = async (studentId) => {
  56 + return await request.get({ url: `/infra/student/student-teacher/get-by-student-id?studentId=` + studentId })
  57 +}
0 \ No newline at end of file 58 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentContactForm 0 → 100644
  1 +<template>
  2 + <el-form
  3 + ref="formRef"
  4 + :model="formData"
  5 + :rules="formRules"
  6 + v-loading="formLoading"
  7 + label-width="0px"
  8 + :inline-message="true"
  9 + >
  10 + <el-table :data="formData" class="-mt-10px">
  11 + <el-table-column label="序号" type="index" width="100" />
  12 + <el-table-column label="名字" min-width="150">
  13 + <template #default="{ row, $index }">
  14 + <el-form-item :prop="`${$index}.name`" :rules="formRules.name" class="mb-0px!">
  15 + <el-input v-model="row.name" placeholder="请输入名字" />
  16 + </el-form-item>
  17 + </template>
  18 + </el-table-column>
  19 + <el-table-column label="简介" min-width="200">
  20 + <template #default="{ row, $index }">
  21 + <el-form-item :prop="`${$index}.description`" :rules="formRules.description" class="mb-0px!">
  22 + <el-input v-model="row.description" type="textarea" placeholder="请输入简介" />
  23 + </el-form-item>
  24 + </template>
  25 + </el-table-column>
  26 + <el-table-column label="出生日期" min-width="150">
  27 + <template #default="{ row, $index }">
  28 + <el-form-item :prop="`${$index}.birthday`" :rules="formRules.birthday" class="mb-0px!">
  29 + <el-date-picker
  30 + v-model="row.birthday"
  31 + type="date"
  32 + value-format="x"
  33 + placeholder="选择出生日期"
  34 + />
  35 + </el-form-item>
  36 + </template>
  37 + </el-table-column>
  38 + <el-table-column label="性别" min-width="150">
  39 + <template #default="{ row, $index }">
  40 + <el-form-item :prop="`${$index}.sex`" :rules="formRules.sex" class="mb-0px!">
  41 + <el-select v-model="row.sex" placeholder="请选择性别">
  42 + <el-option
  43 + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
  44 + :key="dict.value"
  45 + :label="dict.label"
  46 + :value="dict.value"
  47 + />
  48 + </el-select>
  49 + </el-form-item>
  50 + </template>
  51 + </el-table-column>
  52 + <el-table-column label="是否有效" min-width="150">
  53 + <template #default="{ row, $index }">
  54 + <el-form-item :prop="`${$index}.enabled`" :rules="formRules.enabled" class="mb-0px!">
  55 + <el-radio-group v-model="row.enabled">
  56 + <el-radio
  57 + v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
  58 + :key="dict.value"
  59 + :label="dict.value"
  60 + >
  61 + {{ dict.label }}
  62 + </el-radio>
  63 + </el-radio-group>
  64 + </el-form-item>
  65 + </template>
  66 + </el-table-column>
  67 + <el-table-column label="头像" min-width="200">
  68 + <template #default="{ row, $index }">
  69 + <el-form-item :prop="`${$index}.avatar`" :rules="formRules.avatar" class="mb-0px!">
  70 + <UploadImg v-model="row.avatar" />
  71 + </el-form-item>
  72 + </template>
  73 + </el-table-column>
  74 + <el-table-column label="附件" min-width="200">
  75 + <template #default="{ row, $index }">
  76 + <el-form-item :prop="`${$index}.video`" :rules="formRules.video" class="mb-0px!">
  77 + <UploadFile v-model="row.video" />
  78 + </el-form-item>
  79 + </template>
  80 + </el-table-column>
  81 + <el-table-column label="备注" min-width="400">
  82 + <template #default="{ row, $index }">
  83 + <el-form-item :prop="`${$index}.memo`" :rules="formRules.memo" class="mb-0px!">
  84 + <Editor v-model="row.memo" height="150px" />
  85 + </el-form-item>
  86 + </template>
  87 + </el-table-column>
  88 + <el-table-column align="center" fixed="right" label="操作" width="60">
  89 + <template #default="{ $index }">
  90 + <el-button @click="handleDelete($index)" link>—</el-button>
  91 + </template>
  92 + </el-table-column>
  93 + </el-table>
  94 + </el-form>
  95 + <el-row justify="center" class="mt-3">
  96 + <el-button @click="handleAdd" round>+ 添加学生联系人</el-button>
  97 + </el-row>
  98 +</template>
  99 +<script setup lang="ts">
  100 +import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
  101 +import * as StudentApi from '@/api/infra/demo'
  102 +
  103 +const props = defineProps<{
  104 + studentId: undefined // 学生编号(主表的关联字段)
  105 +}>()
  106 +const formLoading = ref(false) // 表单的加载中
  107 +const formData = ref([])
  108 +const formRules = reactive({
  109 + studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
  110 + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
  111 + description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
  112 + birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
  113 + sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
  114 + enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
  115 + avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
  116 + memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
  117 +})
  118 +const formRef = ref() // 表单 Ref
  119 +
  120 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  121 +watch(
  122 + () => props.studentId,
  123 + async (val) => {
  124 + // 1. 重置表单
  125 + formData.value = []
  126 + // 2. val 非空,则加载数据
  127 + if (!val) {
  128 + return;
  129 + }
  130 + try {
  131 + formLoading.value = true
  132 + formData.value = await StudentApi.getStudentContactListByStudentId(val)
  133 + } finally {
  134 + formLoading.value = false
  135 + }
  136 + },
  137 + { immediate: true }
  138 +)
  139 +
  140 +/** 新增按钮操作 */
  141 +const handleAdd = () => {
  142 + const row = {
  143 + id: undefined,
  144 + studentId: undefined,
  145 + name: undefined,
  146 + description: undefined,
  147 + birthday: undefined,
  148 + sex: undefined,
  149 + enabled: undefined,
  150 + avatar: undefined,
  151 + video: undefined,
  152 + memo: undefined
  153 + }
  154 + row.studentId = props.studentId
  155 + formData.value.push(row)
  156 +}
  157 +
  158 +/** 删除按钮操作 */
  159 +const handleDelete = (index) => {
  160 + formData.value.splice(index, 1)
  161 +}
  162 +
  163 +/** 表单校验 */
  164 +const validate = () => {
  165 + return formRef.value.validate()
  166 +}
  167 +
  168 +/** 表单值 */
  169 +const getData = () => {
  170 + return formData.value
  171 +}
  172 +
  173 +defineExpose({ validate, getData })
  174 +</script>
0 \ No newline at end of file 175 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentContactList 0 → 100644
  1 +<template>
  2 + <!-- 列表 -->
  3 + <ContentWrap>
  4 + <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
  5 + <el-table-column label="编号" align="center" prop="id" />
  6 + <el-table-column label="名字" align="center" prop="name" />
  7 + <el-table-column label="简介" align="center" prop="description" />
  8 + <el-table-column
  9 + label="出生日期"
  10 + align="center"
  11 + prop="birthday"
  12 + :formatter="dateFormatter"
  13 + width="180px"
  14 + />
  15 + <el-table-column label="性别" align="center" prop="sex">
  16 + <template #default="scope">
  17 + <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
  18 + </template>
  19 + </el-table-column>
  20 + <el-table-column label="是否有效" align="center" prop="enabled">
  21 + <template #default="scope">
  22 + <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
  23 + </template>
  24 + </el-table-column>
  25 + <el-table-column label="头像" align="center" prop="avatar" />
  26 + <el-table-column label="附件" align="center" prop="video" />
  27 + <el-table-column label="备注" align="center" prop="memo" />
  28 + <el-table-column
  29 + label="创建时间"
  30 + align="center"
  31 + prop="createTime"
  32 + :formatter="dateFormatter"
  33 + width="180px"
  34 + />
  35 + </el-table>
  36 + </ContentWrap>
  37 +</template>
  38 +<script setup lang="ts">
  39 +import { DICT_TYPE } from '@/utils/dict'
  40 +import { dateFormatter } from '@/utils/formatTime'
  41 +import * as StudentApi from '@/api/infra/demo'
  42 +
  43 +const { t } = useI18n() // 国际化
  44 +const message = useMessage() // 消息弹窗
  45 +
  46 +const props = defineProps<{
  47 + studentId: undefined // 学生编号(主表的关联字段)
  48 +}>()
  49 +const loading = ref(false) // 列表的加载中
  50 +const list = ref([]) // 列表的数据
  51 +
  52 +/** 查询列表 */
  53 +const getList = async () => {
  54 + loading.value = true
  55 + try {
  56 + list.value = await StudentApi.getStudentContactListByStudentId(props.studentId)
  57 + } finally {
  58 + loading.value = false
  59 + }
  60 +}
  61 +
  62 +/** 搜索按钮操作 */
  63 +const handleQuery = () => {
  64 + queryParams.pageNo = 1
  65 + getList()
  66 +}
  67 +
  68 +/** 初始化 **/
  69 +onMounted(() => {
  70 + getList()
  71 +})
  72 +</script>
0 \ No newline at end of file 73 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentForm 0 → 100644
  1 +<template>
  2 + <Dialog :title="dialogTitle" v-model="dialogVisible">
  3 + <el-form
  4 + ref="formRef"
  5 + :model="formData"
  6 + :rules="formRules"
  7 + label-width="100px"
  8 + v-loading="formLoading"
  9 + >
  10 + <el-form-item label="名字" prop="name">
  11 + <el-input v-model="formData.name" placeholder="请输入名字" />
  12 + </el-form-item>
  13 + <el-form-item label="简介" prop="description">
  14 + <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
  15 + </el-form-item>
  16 + <el-form-item label="出生日期" prop="birthday">
  17 + <el-date-picker
  18 + v-model="formData.birthday"
  19 + type="date"
  20 + value-format="x"
  21 + placeholder="选择出生日期"
  22 + />
  23 + </el-form-item>
  24 + <el-form-item label="性别" prop="sex">
  25 + <el-select v-model="formData.sex" placeholder="请选择性别">
  26 + <el-option
  27 + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
  28 + :key="dict.value"
  29 + :label="dict.label"
  30 + :value="dict.value"
  31 + />
  32 + </el-select>
  33 + </el-form-item>
  34 + <el-form-item label="是否有效" prop="enabled">
  35 + <el-radio-group v-model="formData.enabled">
  36 + <el-radio
  37 + v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
  38 + :key="dict.value"
  39 + :label="dict.value"
  40 + >
  41 + {{ dict.label }}
  42 + </el-radio>
  43 + </el-radio-group>
  44 + </el-form-item>
  45 + <el-form-item label="头像" prop="avatar">
  46 + <UploadImg v-model="formData.avatar" />
  47 + </el-form-item>
  48 + <el-form-item label="附件" prop="video">
  49 + <UploadFile v-model="formData.video" />
  50 + </el-form-item>
  51 + <el-form-item label="备注" prop="memo">
  52 + <Editor v-model="formData.memo" height="150px" />
  53 + </el-form-item>
  54 + </el-form>
  55 + <!-- 子表的表单 -->
  56 + <el-tabs v-model="subTabsName">
  57 + <el-tab-pane label="学生联系人" name="studentContact">
  58 + <StudentContactForm ref="studentContactFormRef" :student-id="formData.id" />
  59 + </el-tab-pane>
  60 + <el-tab-pane label="学生班主任" name="studentTeacher">
  61 + <StudentTeacherForm ref="studentTeacherFormRef" :student-id="formData.id" />
  62 + </el-tab-pane>
  63 + </el-tabs>
  64 + <template #footer>
  65 + <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
  66 + <el-button @click="dialogVisible = false">取 消</el-button>
  67 + </template>
  68 + </Dialog>
  69 +</template>
  70 +<script setup lang="ts">
  71 +import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
  72 +import * as StudentApi from '@/api/infra/demo'
  73 +import StudentContactForm from './components/StudentContactForm.vue'
  74 +import StudentTeacherForm from './components/StudentTeacherForm.vue'
  75 +
  76 +const { t } = useI18n() // 国际化
  77 +const message = useMessage() // 消息弹窗
  78 +
  79 +const dialogVisible = ref(false) // 弹窗的是否展示
  80 +const dialogTitle = ref('') // 弹窗的标题
  81 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  82 +const formType = ref('') // 表单的类型:create - 新增;update - 修改
  83 +const formData = ref({
  84 + id: undefined,
  85 + name: undefined,
  86 + description: undefined,
  87 + birthday: undefined,
  88 + sex: undefined,
  89 + enabled: undefined,
  90 + avatar: undefined,
  91 + video: undefined,
  92 + memo: undefined
  93 +})
  94 +const formRules = reactive({
  95 + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
  96 + description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
  97 + birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
  98 + sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
  99 + enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
  100 + avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
  101 + video: [{ required: true, message: '附件不能为空', trigger: 'blur' }],
  102 + memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
  103 +})
  104 +const formRef = ref() // 表单 Ref
  105 +
  106 +/** 子表的表单 */
  107 +const subTabsName = ref('studentContact')
  108 +const studentContactFormRef = ref()
  109 +const studentTeacherFormRef = ref()
  110 +
  111 +/** 打开弹窗 */
  112 +const open = async (type: string, id?: number) => {
  113 + dialogVisible.value = true
  114 + dialogTitle.value = t('action.' + type)
  115 + formType.value = type
  116 + resetForm()
  117 + // 修改时,设置数据
  118 + if (id) {
  119 + formLoading.value = true
  120 + try {
  121 + formData.value = await StudentApi.getStudent(id)
  122 + } finally {
  123 + formLoading.value = false
  124 + }
  125 + }
  126 +}
  127 +defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  128 +
  129 +/** 提交表单 */
  130 +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  131 +const submitForm = async () => {
  132 + // 校验表单
  133 + await formRef.value.validate()
  134 + // 校验子表单
  135 + try {
  136 + await studentContactFormRef.value.validate()
  137 + } catch (e) {
  138 + subTabsName.value = 'studentContact'
  139 + return
  140 + }
  141 + try {
  142 + await studentTeacherFormRef.value.validate()
  143 + } catch (e) {
  144 + subTabsName.value = 'studentTeacher'
  145 + return
  146 + }
  147 + // 提交请求
  148 + formLoading.value = true
  149 + try {
  150 + const data = formData.value as unknown as StudentApi.StudentVO
  151 + // 拼接子表的数据
  152 + data.studentContacts = studentContactFormRef.value.getData()
  153 + data.studentTeacher = studentTeacherFormRef.value.getData()
  154 + if (formType.value === 'create') {
  155 + await StudentApi.createStudent(data)
  156 + message.success(t('common.createSuccess'))
  157 + } else {
  158 + await StudentApi.updateStudent(data)
  159 + message.success(t('common.updateSuccess'))
  160 + }
  161 + dialogVisible.value = false
  162 + // 发送操作成功的事件
  163 + emit('success')
  164 + } finally {
  165 + formLoading.value = false
  166 + }
  167 +}
  168 +
  169 +/** 重置表单 */
  170 +const resetForm = () => {
  171 + formData.value = {
  172 + id: undefined,
  173 + name: undefined,
  174 + description: undefined,
  175 + birthday: undefined,
  176 + sex: undefined,
  177 + enabled: undefined,
  178 + avatar: undefined,
  179 + video: undefined,
  180 + memo: undefined
  181 + }
  182 + formRef.value?.resetFields()
  183 +}
  184 +</script>
0 \ No newline at end of file 185 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentTeacherForm 0 → 100644
  1 +<template>
  2 + <el-form
  3 + ref="formRef"
  4 + :model="formData"
  5 + :rules="formRules"
  6 + label-width="100px"
  7 + v-loading="formLoading"
  8 + >
  9 + <el-form-item label="名字" prop="name">
  10 + <el-input v-model="formData.name" placeholder="请输入名字" />
  11 + </el-form-item>
  12 + <el-form-item label="简介" prop="description">
  13 + <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
  14 + </el-form-item>
  15 + <el-form-item label="出生日期" prop="birthday">
  16 + <el-date-picker
  17 + v-model="formData.birthday"
  18 + type="date"
  19 + value-format="x"
  20 + placeholder="选择出生日期"
  21 + />
  22 + </el-form-item>
  23 + <el-form-item label="性别" prop="sex">
  24 + <el-select v-model="formData.sex" placeholder="请选择性别">
  25 + <el-option
  26 + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
  27 + :key="dict.value"
  28 + :label="dict.label"
  29 + :value="dict.value"
  30 + />
  31 + </el-select>
  32 + </el-form-item>
  33 + <el-form-item label="是否有效" prop="enabled">
  34 + <el-radio-group v-model="formData.enabled">
  35 + <el-radio
  36 + v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
  37 + :key="dict.value"
  38 + :label="dict.value"
  39 + >
  40 + {{ dict.label }}
  41 + </el-radio>
  42 + </el-radio-group>
  43 + </el-form-item>
  44 + <el-form-item label="头像" prop="avatar">
  45 + <UploadImg v-model="formData.avatar" />
  46 + </el-form-item>
  47 + <el-form-item label="附件" prop="video">
  48 + <UploadFile v-model="formData.video" />
  49 + </el-form-item>
  50 + <el-form-item label="备注" prop="memo">
  51 + <Editor v-model="formData.memo" height="150px" />
  52 + </el-form-item>
  53 + </el-form>
  54 +</template>
  55 +<script setup lang="ts">
  56 +import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
  57 +import * as StudentApi from '@/api/infra/demo'
  58 +
  59 +const props = defineProps<{
  60 + studentId: undefined // 学生编号(主表的关联字段)
  61 +}>()
  62 +const formLoading = ref(false) // 表单的加载中
  63 +const formData = ref([])
  64 +const formRules = reactive({
  65 + studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
  66 + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
  67 + description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
  68 + birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
  69 + sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
  70 + enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
  71 + avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
  72 + memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
  73 +})
  74 +const formRef = ref() // 表单 Ref
  75 +
  76 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  77 +watch(
  78 + () => props.studentId,
  79 + async (val) => {
  80 + // 1. 重置表单
  81 + formData.value = {
  82 + id: undefined,
  83 + studentId: undefined,
  84 + name: undefined,
  85 + description: undefined,
  86 + birthday: undefined,
  87 + sex: undefined,
  88 + enabled: undefined,
  89 + avatar: undefined,
  90 + video: undefined,
  91 + memo: undefined,
  92 + }
  93 + // 2. val 非空,则加载数据
  94 + if (!val) {
  95 + return;
  96 + }
  97 + try {
  98 + formLoading.value = true
  99 + const data = await StudentApi.getStudentTeacherByStudentId(val)
  100 + if (!data) {
  101 + return
  102 + }
  103 + formData.value = data
  104 + } finally {
  105 + formLoading.value = false
  106 + }
  107 + },
  108 + { immediate: true }
  109 +)
  110 +
  111 +/** 表单校验 */
  112 +const validate = () => {
  113 + return formRef.value.validate()
  114 +}
  115 +
  116 +/** 表单值 */
  117 +const getData = () => {
  118 + return formData.value
  119 +}
  120 +
  121 +defineExpose({ validate, getData })
  122 +</script>
0 \ No newline at end of file 123 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentTeacherList 0 → 100644
  1 +<template>
  2 + <!-- 列表 -->
  3 + <ContentWrap>
  4 + <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
  5 + <el-table-column label="编号" align="center" prop="id" />
  6 + <el-table-column label="名字" align="center" prop="name" />
  7 + <el-table-column label="简介" align="center" prop="description" />
  8 + <el-table-column
  9 + label="出生日期"
  10 + align="center"
  11 + prop="birthday"
  12 + :formatter="dateFormatter"
  13 + width="180px"
  14 + />
  15 + <el-table-column label="性别" align="center" prop="sex">
  16 + <template #default="scope">
  17 + <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
  18 + </template>
  19 + </el-table-column>
  20 + <el-table-column label="是否有效" align="center" prop="enabled">
  21 + <template #default="scope">
  22 + <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
  23 + </template>
  24 + </el-table-column>
  25 + <el-table-column label="头像" align="center" prop="avatar" />
  26 + <el-table-column label="附件" align="center" prop="video" />
  27 + <el-table-column label="备注" align="center" prop="memo" />
  28 + <el-table-column
  29 + label="创建时间"
  30 + align="center"
  31 + prop="createTime"
  32 + :formatter="dateFormatter"
  33 + width="180px"
  34 + />
  35 + </el-table>
  36 + </ContentWrap>
  37 +</template>
  38 +<script setup lang="ts">
  39 +import { DICT_TYPE } from '@/utils/dict'
  40 +import { dateFormatter } from '@/utils/formatTime'
  41 +import * as StudentApi from '@/api/infra/demo'
  42 +
  43 +const { t } = useI18n() // 国际化
  44 +const message = useMessage() // 消息弹窗
  45 +
  46 +const props = defineProps<{
  47 + studentId: undefined // 学生编号(主表的关联字段)
  48 +}>()
  49 +const loading = ref(false) // 列表的加载中
  50 +const list = ref([]) // 列表的数据
  51 +
  52 +/** 查询列表 */
  53 +const getList = async () => {
  54 + loading.value = true
  55 + try {
  56 + const data = await StudentApi.getStudentTeacherByStudentId(props.studentId)
  57 + if (!data) {
  58 + return
  59 + }
  60 + list.value.push(data)
  61 + } finally {
  62 + loading.value = false
  63 + }
  64 +}
  65 +
  66 +/** 搜索按钮操作 */
  67 +const handleQuery = () => {
  68 + queryParams.pageNo = 1
  69 + getList()
  70 +}
  71 +
  72 +/** 初始化 **/
  73 +onMounted(() => {
  74 + getList()
  75 +})
  76 +</script>
0 \ No newline at end of file 77 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_crud/vue/index renamed to yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/index
@@ -17,36 +17,46 @@ @@ -17,36 +17,46 @@
17 class="!w-240px" 17 class="!w-240px"
18 /> 18 />
19 </el-form-item> 19 </el-form-item>
20 - <el-form-item label="性别 1" prop="sex1">  
21 - <el-select v-model="queryParams.sex1" placeholder="请选择性别 1" clearable class="!w-240px"> 20 + <el-form-item label="出生日期" prop="birthday">
  21 + <el-date-picker
  22 + v-model="queryParams.birthday"
  23 + value-format="YYYY-MM-DD"
  24 + type="date"
  25 + placeholder="选择出生日期"
  26 + clearable
  27 + class="!w-240px"
  28 + />
  29 + </el-form-item>
  30 + <el-form-item label="性别" prop="sex">
  31 + <el-select
  32 + v-model="queryParams.sex"
  33 + placeholder="请选择性别"
  34 + clearable
  35 + class="!w-240px"
  36 + >
22 <el-option 37 <el-option
23 - v-for="dict in getStrDictOptions(DICT_TYPE.SYSTEM_SEX1)" 38 + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
24 :key="dict.value" 39 :key="dict.value"
25 :label="dict.label" 40 :label="dict.label"
26 :value="dict.value" 41 :value="dict.value"
27 /> 42 />
28 </el-select> 43 </el-select>
29 </el-form-item> 44 </el-form-item>
30 - <el-form-item label="性别 3" prop="sex3">  
31 - <el-select v-model="queryParams.sex3" placeholder="请选择性别 3" clearable class="!w-240px"> 45 + <el-form-item label="是否有效" prop="enabled">
  46 + <el-select
  47 + v-model="queryParams.enabled"
  48 + placeholder="请选择是否有效"
  49 + clearable
  50 + class="!w-240px"
  51 + >
32 <el-option 52 <el-option
33 - v-for="dict in getBoolDictOptions(DICT_TYPE.SYSTEM_SEX3)" 53 + v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
34 :key="dict.value" 54 :key="dict.value"
35 :label="dict.label" 55 :label="dict.label"
36 :value="dict.value" 56 :value="dict.value"
37 /> 57 />
38 </el-select> 58 </el-select>
39 </el-form-item> 59 </el-form-item>
40 - <el-form-item label="出生日期" prop="birthday">  
41 - <el-date-picker  
42 - v-model="queryParams.birthday"  
43 - value-format="YYYY-MM-DD"  
44 - type="date"  
45 - placeholder="选择出生日期"  
46 - clearable  
47 - class="!w-240px"  
48 - />  
49 - </el-form-item>  
50 <el-form-item label="创建时间" prop="createTime"> 60 <el-form-item label="创建时间" prop="createTime">
51 <el-date-picker 61 <el-date-picker
52 v-model="queryParams.createTime" 62 v-model="queryParams.createTime"
@@ -61,7 +71,12 @@ @@ -61,7 +71,12 @@
61 <el-form-item> 71 <el-form-item>
62 <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> 72 <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
63 <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> 73 <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
64 - <el-button type="primary" @click="openForm('create')" v-hasPermi="['system:user:create']"> 74 + <el-button
  75 + type="primary"
  76 + plain
  77 + @click="openForm('create')"
  78 + v-hasPermi="['infra:student:create']"
  79 + >
65 <Icon icon="ep:plus" class="mr-5px" /> 新增 80 <Icon icon="ep:plus" class="mr-5px" /> 新增
66 </el-button> 81 </el-button>
67 <el-button 82 <el-button
@@ -69,7 +84,7 @@ @@ -69,7 +84,7 @@
69 plain 84 plain
70 @click="handleExport" 85 @click="handleExport"
71 :loading="exportLoading" 86 :loading="exportLoading"
72 - v-hasPermi="['system:user:export']" 87 + v-hasPermi="['infra:student:export']"
73 > 88 >
74 <Icon icon="ep:download" class="mr-5px" /> 导出 89 <Icon icon="ep:download" class="mr-5px" /> 导出
75 </el-button> 90 </el-button>
@@ -80,46 +95,22 @@ @@ -80,46 +95,22 @@
80 <!-- 列表 --> 95 <!-- 列表 -->
81 <ContentWrap> 96 <ContentWrap>
82 <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> 97 <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
83 - <el-table-column label="编号" align="center" prop="id">  
84 - <template #default="scope">  
85 - <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.id" />  
86 - </template>  
87 - </el-table-column>  
88 - <el-table-column label="名字" align="center" prop="name">  
89 - <template #default="scope">  
90 - <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.name" />  
91 - </template>  
92 - </el-table-column>  
93 - <el-table-column label="头像" align="center" prop="avatar"> 98 + <!-- 子表的列表 -->
  99 + <el-table-column type="expand">
94 <template #default="scope"> 100 <template #default="scope">
95 - <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.avatar" />  
96 - </template>  
97 - </el-table-column>  
98 - <el-table-column label="视频" align="center" prop="video">  
99 - <template #default="scope">  
100 - <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.video" />  
101 - </template>  
102 - </el-table-column>  
103 - <el-table-column label="个人简介" align="center" prop="description">  
104 - <template #default="scope">  
105 - <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.description" />  
106 - </template>  
107 - </el-table-column>  
108 - <el-table-column label="性别 1" align="center" prop="sex1">  
109 - <template #default="scope">  
110 - <dict-tag :type="DICT_TYPE.SYSTEM_SEX1" :value="scope.row.sex1" />  
111 - </template>  
112 - </el-table-column>  
113 - <el-table-column label="性别 2" align="center" prop="sex2">  
114 - <template #default="scope">  
115 - <dict-tag :type="DICT_TYPE.SYSTEM_SEX2" :value="scope.row.sex2" />  
116 - </template>  
117 - </el-table-column>  
118 - <el-table-column label="性别 3" align="center" prop="sex3">  
119 - <template #default="scope">  
120 - <dict-tag :type="DICT_TYPE.SYSTEM_SEX3" :value="scope.row.sex3" /> 101 + <el-tabs model-value="studentContact">
  102 + <el-tab-pane label="学生联系人" name="studentContact">
  103 + <StudentContactList :student-id="scope.row.id" />
  104 + </el-tab-pane>
  105 + <el-tab-pane label="学生班主任" name="studentTeacher">
  106 + <StudentTeacherList :student-id="scope.row.id" />
  107 + </el-tab-pane>
  108 + </el-tabs>
121 </template> 109 </template>
122 </el-table-column> 110 </el-table-column>
  111 + <el-table-column label="编号" align="center" prop="id" />
  112 + <el-table-column label="名字" align="center" prop="name" />
  113 + <el-table-column label="简介" align="center" prop="description" />
123 <el-table-column 114 <el-table-column
124 label="出生日期" 115 label="出生日期"
125 align="center" 116 align="center"
@@ -127,11 +118,19 @@ @@ -127,11 +118,19 @@
127 :formatter="dateFormatter" 118 :formatter="dateFormatter"
128 width="180px" 119 width="180px"
129 /> 120 />
130 - <el-table-column label="备注" align="center" prop="memo"> 121 + <el-table-column label="性别" align="center" prop="sex">
  122 + <template #default="scope">
  123 + <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
  124 + </template>
  125 + </el-table-column>
  126 + <el-table-column label="是否有效" align="center" prop="enabled">
131 <template #default="scope"> 127 <template #default="scope">
132 - <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.memo" /> 128 + <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
133 </template> 129 </template>
134 </el-table-column> 130 </el-table-column>
  131 + <el-table-column label="头像" align="center" prop="avatar" />
  132 + <el-table-column label="附件" align="center" prop="video" />
  133 + <el-table-column label="备注" align="center" prop="memo" />
135 <el-table-column 134 <el-table-column
136 label="创建时间" 135 label="创建时间"
137 align="center" 136 align="center"
@@ -145,7 +144,7 @@ @@ -145,7 +144,7 @@
145 link 144 link
146 type="primary" 145 type="primary"
147 @click="openForm('update', scope.row.id)" 146 @click="openForm('update', scope.row.id)"
148 - v-hasPermi="['system:user:update']" 147 + v-hasPermi="['infra:student:update']"
149 > 148 >
150 编辑 149 编辑
151 </el-button> 150 </el-button>
@@ -153,7 +152,7 @@ @@ -153,7 +152,7 @@
153 link 152 link
154 type="danger" 153 type="danger"
155 @click="handleDelete(scope.row.id)" 154 @click="handleDelete(scope.row.id)"
156 - v-hasPermi="['system:user:delete']" 155 + v-hasPermi="['infra:student:delete']"
157 > 156 >
158 删除 157 删除
159 </el-button> 158 </el-button>
@@ -170,33 +169,34 @@ @@ -170,33 +169,34 @@
170 </ContentWrap> 169 </ContentWrap>
171 170
172 <!-- 表单弹窗:添加/修改 --> 171 <!-- 表单弹窗:添加/修改 -->
173 - <UserForm ref="formRef" @success="getList" /> 172 + <StudentForm ref="formRef" @success="getList" />
174 </template> 173 </template>
175 174
176 <script setup lang="ts"> 175 <script setup lang="ts">
177 -import { DICT_TYPE, getStrDictOptions, getBoolDictOptions } from '@/utils/dict' 176 +import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
178 import { dateFormatter } from '@/utils/formatTime' 177 import { dateFormatter } from '@/utils/formatTime'
179 import download from '@/utils/download' 178 import download from '@/utils/download'
180 -import * as UserApi from '@/api/system/user'  
181 -import UserForm from './UserForm.vue' 179 +import * as StudentApi from '@/api/infra/demo'
  180 +import StudentForm from './StudentForm.vue'
  181 +import StudentContactList from './components/StudentContactList.vue'
  182 +import StudentTeacherList from './components/StudentTeacherList.vue'
182 183
183 -defineOptions({ name: 'SystemUser' }) 184 +defineOptions({ name: 'InfraStudent' })
184 185
185 const message = useMessage() // 消息弹窗 186 const message = useMessage() // 消息弹窗
186 const { t } = useI18n() // 国际化 187 const { t } = useI18n() // 国际化
187 188
188 const loading = ref(true) // 列表的加载中 189 const loading = ref(true) // 列表的加载中
189 -const total = ref(0) // 列表的总页数  
190 const list = ref([]) // 列表的数据 190 const list = ref([]) // 列表的数据
  191 +const total = ref(0) // 列表的总页数
191 const queryParams = reactive({ 192 const queryParams = reactive({
192 pageNo: 1, 193 pageNo: 1,
193 pageSize: 10, 194 pageSize: 10,
194 name: null, 195 name: null,
195 - sex1: null,  
196 - sex2: null,  
197 - sex3: null,  
198 birthday: null, 196 birthday: null,
199 birthday: [], 197 birthday: [],
  198 + sex: null,
  199 + enabled: null,
200 createTime: [] 200 createTime: []
201 }) 201 })
202 const queryFormRef = ref() // 搜索的表单 202 const queryFormRef = ref() // 搜索的表单
@@ -206,7 +206,7 @@ const exportLoading = ref(false) // 导出的加载中 @@ -206,7 +206,7 @@ const exportLoading = ref(false) // 导出的加载中
206 const getList = async () => { 206 const getList = async () => {
207 loading.value = true 207 loading.value = true
208 try { 208 try {
209 - const data = await UserApi.getUserPage(queryParams) 209 + const data = await StudentApi.getStudentPage(queryParams)
210 list.value = data.list 210 list.value = data.list
211 total.value = data.total 211 total.value = data.total
212 } finally { 212 } finally {
@@ -238,7 +238,7 @@ const handleDelete = async (id: number) =&gt; { @@ -238,7 +238,7 @@ const handleDelete = async (id: number) =&gt; {
238 // 删除的二次确认 238 // 删除的二次确认
239 await message.delConfirm() 239 await message.delConfirm()
240 // 发起删除 240 // 发起删除
241 - await UserApi.deleteUser(id) 241 + await StudentApi.deleteStudent(id)
242 message.success(t('common.delSuccess')) 242 message.success(t('common.delSuccess'))
243 // 刷新列表 243 // 刷新列表
244 await getList() 244 await getList()
@@ -252,8 +252,8 @@ const handleExport = async () =&gt; { @@ -252,8 +252,8 @@ const handleExport = async () =&gt; {
252 await message.exportConfirm() 252 await message.exportConfirm()
253 // 发起导出 253 // 发起导出
254 exportLoading.value = true 254 exportLoading.value = true
255 - const data = await UserApi.exportUser(queryParams)  
256 - download.excel(data, '用户.xls') 255 + const data = await StudentApi.exportStudent(queryParams)
  256 + download.excel(data, '学生.xls')
257 } catch { 257 } catch {
258 } finally { 258 } finally {
259 exportLoading.value = false 259 exportLoading.value = false
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/xml/InfraStudentMapper 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper">
  4 +
  5 + <!--
  6 + 一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
  7 + 无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
  8 + 代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
  9 + 文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
  10 + -->
  11 +
  12 +</mapper>
0 \ No newline at end of file 13 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/assert.json
1 -[{  
2 - "filePath": "",  
3 - "contentPath": ""  
4 -}]  
5 \ No newline at end of file 1 \ No newline at end of file
  2 +[ {
  3 + "contentPath" : "java/InfraStudentPageReqVO",
  4 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java"
  5 +}, {
  6 + "contentPath" : "java/InfraStudentRespVO",
  7 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java"
  8 +}, {
  9 + "contentPath" : "java/InfraStudentSaveReqVO",
  10 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java"
  11 +}, {
  12 + "contentPath" : "java/InfraStudentController",
  13 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java"
  14 +}, {
  15 + "contentPath" : "java/InfraStudentDO",
  16 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java"
  17 +}, {
  18 + "contentPath" : "java/InfraStudentContactDO",
  19 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java"
  20 +}, {
  21 + "contentPath" : "java/InfraStudentTeacherDO",
  22 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java"
  23 +}, {
  24 + "contentPath" : "java/InfraStudentMapper",
  25 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java"
  26 +}, {
  27 + "contentPath" : "java/InfraStudentContactMapper",
  28 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java"
  29 +}, {
  30 + "contentPath" : "java/InfraStudentTeacherMapper",
  31 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java"
  32 +}, {
  33 + "contentPath" : "xml/InfraStudentMapper",
  34 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml"
  35 +}, {
  36 + "contentPath" : "java/InfraStudentServiceImpl",
  37 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java"
  38 +}, {
  39 + "contentPath" : "java/InfraStudentService",
  40 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java"
  41 +}, {
  42 + "contentPath" : "java/InfraStudentServiceImplTest",
  43 + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java"
  44 +}, {
  45 + "contentPath" : "java/ErrorCodeConstants_手动操作",
  46 + "filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java"
  47 +}, {
  48 + "contentPath" : "sql/sql",
  49 + "filePath" : "sql/sql.sql"
  50 +}, {
  51 + "contentPath" : "sql/h2",
  52 + "filePath" : "sql/h2.sql"
  53 +}, {
  54 + "contentPath" : "vue/index",
  55 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue"
  56 +}, {
  57 + "contentPath" : "vue/StudentForm",
  58 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/StudentForm.vue"
  59 +}, {
  60 + "contentPath" : "vue/StudentContactForm",
  61 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactForm.vue"
  62 +}, {
  63 + "contentPath" : "vue/StudentTeacherForm",
  64 + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherForm.vue"
  65 +}, {
  66 + "contentPath" : "ts/index",
  67 + "filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts"
  68 +} ]
6 \ No newline at end of file 69 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/ErrorCodeConstants_手动操作 0 → 100644
  1 +// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!!
  2 +// ========== 学生 TODO 补充编号 ==========
  3 +ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在");
0 \ No newline at end of file 4 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentContactDO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import java.time.LocalDateTime;
  6 +import java.time.LocalDateTime;
  7 +import com.baomidou.mybatisplus.annotation.*;
  8 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  9 +
  10 +/**
  11 + * 学生联系人 DO
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@TableName("infra_student_contact")
  16 +@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class InfraStudentContactDO extends BaseDO {
  24 +
  25 + /**
  26 + * 编号
  27 + */
  28 + @TableId
  29 + private Long id;
  30 + /**
  31 + * 学生编号
  32 + */
  33 + private Long studentId;
  34 + /**
  35 + * 名字
  36 + */
  37 + private String name;
  38 + /**
  39 + * 简介
  40 + */
  41 + private String description;
  42 + /**
  43 + * 出生日期
  44 + */
  45 + private LocalDateTime birthday;
  46 + /**
  47 + * 性别
  48 + *
  49 + * 枚举 {@link TODO system_user_sex 对应的类}
  50 + */
  51 + private Integer sex;
  52 + /**
  53 + * 是否有效
  54 + *
  55 + * 枚举 {@link TODO infra_boolean_string 对应的类}
  56 + */
  57 + private Boolean enabled;
  58 + /**
  59 + * 头像
  60 + */
  61 + private String avatar;
  62 + /**
  63 + * 附件
  64 + */
  65 + private String video;
  66 + /**
  67 + * 备注
  68 + */
  69 + private String memo;
  70 +
  71 +}
0 \ No newline at end of file 72 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentContactMapper 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.mysql.demo;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  8 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  9 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  10 +import org.apache.ibatis.annotations.Mapper;
  11 +
  12 +/**
  13 + * 学生联系人 Mapper
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Mapper
  18 +public interface InfraStudentContactMapper extends BaseMapperX<InfraStudentContactDO> {
  19 +
  20 + default List<InfraStudentContactDO> selectListByStudentId(Long studentId) {
  21 + return selectList(InfraStudentContactDO::getStudentId, studentId);
  22 + }
  23 +
  24 + default int deleteByStudentId(Long studentId) {
  25 + return delete(InfraStudentContactDO::getStudentId, studentId);
  26 + }
  27 +
  28 +}
0 \ No newline at end of file 29 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentController 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.controller.admin.demo;
  2 +
  3 +import org.springframework.web.bind.annotation.*;
  4 +import javax.annotation.Resource;
  5 +import org.springframework.validation.annotation.Validated;
  6 +import org.springframework.security.access.prepost.PreAuthorize;
  7 +import io.swagger.v3.oas.annotations.tags.Tag;
  8 +import io.swagger.v3.oas.annotations.Parameter;
  9 +import io.swagger.v3.oas.annotations.Operation;
  10 +
  11 +import javax.validation.constraints.*;
  12 +import javax.validation.*;
  13 +import javax.servlet.http.*;
  14 +import java.util.*;
  15 +import java.io.IOException;
  16 +
  17 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  18 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  19 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  20 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  21 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  22 +
  23 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  24 +
  25 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
  26 +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
  27 +
  28 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  29 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  30 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  31 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  32 +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService;
  33 +
  34 +@Tag(name = "管理后台 - 学生")
  35 +@RestController
  36 +@RequestMapping("/infra/student")
  37 +@Validated
  38 +public class InfraStudentController {
  39 +
  40 + @Resource
  41 + private InfraStudentService studentService;
  42 +
  43 + @PostMapping("/create")
  44 + @Operation(summary = "创建学生")
  45 + @PreAuthorize("@ss.hasPermission('infra:student:create')")
  46 + public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) {
  47 + return success(studentService.createStudent(createReqVO));
  48 + }
  49 +
  50 + @PutMapping("/update")
  51 + @Operation(summary = "更新学生")
  52 + @PreAuthorize("@ss.hasPermission('infra:student:update')")
  53 + public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) {
  54 + studentService.updateStudent(updateReqVO);
  55 + return success(true);
  56 + }
  57 +
  58 + @DeleteMapping("/delete")
  59 + @Operation(summary = "删除学生")
  60 + @Parameter(name = "id", description = "编号", required = true)
  61 + @PreAuthorize("@ss.hasPermission('infra:student:delete')")
  62 + public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) {
  63 + studentService.deleteStudent(id);
  64 + return success(true);
  65 + }
  66 +
  67 + @GetMapping("/get")
  68 + @Operation(summary = "获得学生")
  69 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  70 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  71 + public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) {
  72 + InfraStudentDO student = studentService.getStudent(id);
  73 + return success(BeanUtils.toBean(student, InfraStudentRespVO.class));
  74 + }
  75 +
  76 + @GetMapping("/page")
  77 + @Operation(summary = "获得学生分页")
  78 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  79 + public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) {
  80 + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO);
  81 + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class));
  82 + }
  83 +
  84 + @GetMapping("/export-excel")
  85 + @Operation(summary = "导出学生 Excel")
  86 + @PreAuthorize("@ss.hasPermission('infra:student:export')")
  87 + @OperateLog(type = EXPORT)
  88 + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO,
  89 + HttpServletResponse response) throws IOException {
  90 + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
  91 + List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList();
  92 + // 导出 Excel
  93 + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class,
  94 + BeanUtils.toBean(list, InfraStudentRespVO.class));
  95 + }
  96 +
  97 + // ==================== 子表(学生联系人) ====================
  98 +
  99 + @GetMapping("/student-contact/list-by-student-id")
  100 + @Operation(summary = "获得学生联系人列表")
  101 + @Parameter(name = "studentId", description = "学生编号")
  102 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  103 + public CommonResult<List<InfraStudentContactDO>> getStudentContactListByStudentId(@RequestParam("studentId") Long studentId) {
  104 + return success(studentService.getStudentContactListByStudentId(studentId));
  105 + }
  106 +
  107 + // ==================== 子表(学生班主任) ====================
  108 +
  109 + @GetMapping("/student-teacher/get-by-student-id")
  110 + @Operation(summary = "获得学生班主任")
  111 + @Parameter(name = "studentId", description = "学生编号")
  112 + @PreAuthorize("@ss.hasPermission('infra:student:query')")
  113 + public CommonResult<InfraStudentTeacherDO> getStudentTeacherByStudentId(@RequestParam("studentId") Long studentId) {
  114 + return success(studentService.getStudentTeacherByStudentId(studentId));
  115 + }
  116 +
  117 +}
0 \ No newline at end of file 118 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentDO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import java.time.LocalDateTime;
  6 +import java.time.LocalDateTime;
  7 +import com.baomidou.mybatisplus.annotation.*;
  8 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  9 +
  10 +/**
  11 + * 学生 DO
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@TableName("infra_student")
  16 +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class InfraStudentDO extends BaseDO {
  24 +
  25 + /**
  26 + * 编号
  27 + */
  28 + @TableId
  29 + private Long id;
  30 + /**
  31 + * 名字
  32 + */
  33 + private String name;
  34 + /**
  35 + * 简介
  36 + */
  37 + private String description;
  38 + /**
  39 + * 出生日期
  40 + */
  41 + private LocalDateTime birthday;
  42 + /**
  43 + * 性别
  44 + *
  45 + * 枚举 {@link TODO system_user_sex 对应的类}
  46 + */
  47 + private Integer sex;
  48 + /**
  49 + * 是否有效
  50 + *
  51 + * 枚举 {@link TODO infra_boolean_string 对应的类}
  52 + */
  53 + private Boolean enabled;
  54 + /**
  55 + * 头像
  56 + */
  57 + private String avatar;
  58 + /**
  59 + * 附件
  60 + */
  61 + private String video;
  62 + /**
  63 + * 备注
  64 + */
  65 + private String memo;
  66 +
  67 +}
0 \ No newline at end of file 68 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentMapper 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.mysql.demo;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  7 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  8 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  9 +import org.apache.ibatis.annotations.Mapper;
  10 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  11 +
  12 +/**
  13 + * 学生 Mapper
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Mapper
  18 +public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> {
  19 +
  20 + default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) {
  21 + return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>()
  22 + .likeIfPresent(InfraStudentDO::getName, reqVO.getName())
  23 + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday())
  24 + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex())
  25 + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled())
  26 + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime())
  27 + .orderByDesc(InfraStudentDO::getId));
  28 + }
  29 +
  30 +}
0 \ No newline at end of file 31 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentPageReqVO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +import java.time.LocalDateTime;
  9 +
  10 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  11 +
  12 +@Schema(description = "管理后台 - 学生分页 Request VO")
  13 +@Data
  14 +@EqualsAndHashCode(callSuper = true)
  15 +@ToString(callSuper = true)
  16 +public class InfraStudentPageReqVO extends PageParam {
  17 +
  18 + @Schema(description = "名字", example = "芋头")
  19 + private String name;
  20 +
  21 + @Schema(description = "出生日期")
  22 + private LocalDateTime birthday;
  23 +
  24 + @Schema(description = "性别", example = "1")
  25 + private Integer sex;
  26 +
  27 + @Schema(description = "是否有效", example = "true")
  28 + private Boolean enabled;
  29 +
  30 + @Schema(description = "创建时间")
  31 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  32 + private LocalDateTime[] createTime;
  33 +
  34 +}
0 \ No newline at end of file 35 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentRespVO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import java.util.*;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +import java.time.LocalDateTime;
  9 +import com.alibaba.excel.annotation.*;
  10 +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
  11 +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
  12 +
  13 +@Schema(description = "管理后台 - 学生 Response VO")
  14 +@Data
  15 +@ExcelIgnoreUnannotated
  16 +public class InfraStudentRespVO {
  17 +
  18 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  19 + @ExcelProperty("编号")
  20 + private Long id;
  21 +
  22 + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
  23 + @ExcelProperty("名字")
  24 + private String name;
  25 +
  26 + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
  27 + @ExcelProperty("简介")
  28 + private String description;
  29 +
  30 + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
  31 + @ExcelProperty("出生日期")
  32 + private LocalDateTime birthday;
  33 +
  34 + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  35 + @ExcelProperty(value = "性别", converter = DictConvert.class)
  36 + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
  37 + private Integer sex;
  38 +
  39 + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  40 + @ExcelProperty(value = "是否有效", converter = DictConvert.class)
  41 + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
  42 + private Boolean enabled;
  43 +
  44 + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
  45 + @ExcelProperty("头像")
  46 + private String avatar;
  47 +
  48 + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
  49 + @ExcelProperty("附件")
  50 + private String video;
  51 +
  52 + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
  53 + @ExcelProperty("备注")
  54 + private String memo;
  55 +
  56 + @Schema(description = "创建时间")
  57 + @ExcelProperty("创建时间")
  58 + private LocalDateTime createTime;
  59 +
  60 +}
0 \ No newline at end of file 61 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentSaveReqVO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import javax.validation.constraints.*;
  7 +import java.util.*;
  8 +import org.springframework.format.annotation.DateTimeFormat;
  9 +import java.time.LocalDateTime;
  10 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  11 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  12 +
  13 +@Schema(description = "管理后台 - 学生新增/修改 Request VO")
  14 +@Data
  15 +public class InfraStudentSaveReqVO {
  16 +
  17 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  18 + private Long id;
  19 +
  20 + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
  21 + @NotEmpty(message = "名字不能为空")
  22 + private String name;
  23 +
  24 + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
  25 + @NotEmpty(message = "简介不能为空")
  26 + private String description;
  27 +
  28 + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
  29 + @NotNull(message = "出生日期不能为空")
  30 + private LocalDateTime birthday;
  31 +
  32 + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  33 + @NotNull(message = "性别不能为空")
  34 + private Integer sex;
  35 +
  36 + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  37 + @NotNull(message = "是否有效不能为空")
  38 + private Boolean enabled;
  39 +
  40 + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
  41 + @NotEmpty(message = "头像不能为空")
  42 + private String avatar;
  43 +
  44 + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
  45 + @NotEmpty(message = "附件不能为空")
  46 + private String video;
  47 +
  48 + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
  49 + @NotEmpty(message = "备注不能为空")
  50 + private String memo;
  51 +
  52 + @Schema(description = "学生联系人列表")
  53 + private List<InfraStudentContactDO> studentContacts;
  54 +
  55 + @Schema(description = "学生班主任")
  56 + private InfraStudentTeacherDO studentTeacher;
  57 +
  58 +}
0 \ No newline at end of file 59 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentService 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.service.demo;
  2 +
  3 +import java.util.*;
  4 +import javax.validation.*;
  5 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  6 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  7 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  8 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  9 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  10 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  11 +
  12 +/**
  13 + * 学生 Service 接口
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +public interface InfraStudentService {
  18 +
  19 + /**
  20 + * 创建学生
  21 + *
  22 + * @param createReqVO 创建信息
  23 + * @return 编号
  24 + */
  25 + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO);
  26 +
  27 + /**
  28 + * 更新学生
  29 + *
  30 + * @param updateReqVO 更新信息
  31 + */
  32 + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO);
  33 +
  34 + /**
  35 + * 删除学生
  36 + *
  37 + * @param id 编号
  38 + */
  39 + void deleteStudent(Long id);
  40 +
  41 + /**
  42 + * 获得学生
  43 + *
  44 + * @param id 编号
  45 + * @return 学生
  46 + */
  47 + InfraStudentDO getStudent(Long id);
  48 +
  49 + /**
  50 + * 获得学生分页
  51 + *
  52 + * @param pageReqVO 分页查询
  53 + * @return 学生分页
  54 + */
  55 + PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO);
  56 +
  57 + // ==================== 子表(学生联系人) ====================
  58 +
  59 + /**
  60 + * 获得学生联系人列表
  61 + *
  62 + * @param studentId 学生编号
  63 + * @return 学生联系人列表
  64 + */
  65 + List<InfraStudentContactDO> getStudentContactListByStudentId(Long studentId);
  66 +
  67 + // ==================== 子表(学生班主任) ====================
  68 +
  69 + /**
  70 + * 获得学生班主任
  71 + *
  72 + * @param studentId 学生编号
  73 + * @return 学生班主任
  74 + */
  75 + InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId);
  76 +
  77 +}
0 \ No newline at end of file 78 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentServiceImpl 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.service.demo;
  2 +
  3 +import org.springframework.stereotype.Service;
  4 +import javax.annotation.Resource;
  5 +import org.springframework.validation.annotation.Validated;
  6 +import org.springframework.transaction.annotation.Transactional;
  7 +
  8 +import java.util.*;
  9 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  10 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  11 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
  12 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  13 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  14 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  15 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  16 +
  17 +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
  18 +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper;
  19 +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper;
  20 +
  21 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  22 +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
  23 +
  24 +/**
  25 + * 学生 Service 实现类
  26 + *
  27 + * @author 芋道源码
  28 + */
  29 +@Service
  30 +@Validated
  31 +public class InfraStudentServiceImpl implements InfraStudentService {
  32 +
  33 + @Resource
  34 + private InfraStudentMapper studentMapper;
  35 + @Resource
  36 + private InfraStudentContactMapper studentContactMapper;
  37 + @Resource
  38 + private InfraStudentTeacherMapper studentTeacherMapper;
  39 +
  40 + @Override
  41 + @Transactional(rollbackFor = Exception.class)
  42 + public Long createStudent(InfraStudentSaveReqVO createReqVO) {
  43 + // 插入
  44 + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class);
  45 + studentMapper.insert(student);
  46 +
  47 + // 插入子表
  48 + createStudentContactList(student.getId(), createReqVO.getStudentContacts());
  49 + createStudentTeacher(student.getId(), createReqVO.getStudentTeacher());
  50 + // 返回
  51 + return student.getId();
  52 + }
  53 +
  54 + @Override
  55 + @Transactional(rollbackFor = Exception.class)
  56 + public void updateStudent(InfraStudentSaveReqVO updateReqVO) {
  57 + // 校验存在
  58 + validateStudentExists(updateReqVO.getId());
  59 + // 更新
  60 + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class);
  61 + studentMapper.updateById(updateObj);
  62 +
  63 + // 更新子表
  64 + updateStudentContactList(updateReqVO.getId(), updateReqVO.getStudentContacts());
  65 + updateStudentTeacher(updateReqVO.getId(), updateReqVO.getStudentTeacher());
  66 + }
  67 +
  68 + @Override
  69 + @Transactional(rollbackFor = Exception.class)
  70 + public void deleteStudent(Long id) {
  71 + // 校验存在
  72 + validateStudentExists(id);
  73 + // 删除
  74 + studentMapper.deleteById(id);
  75 +
  76 + // 删除子表
  77 + deleteStudentContactByStudentId(id);
  78 + deleteStudentTeacherByStudentId(id);
  79 + }
  80 +
  81 + private void validateStudentExists(Long id) {
  82 + if (studentMapper.selectById(id) == null) {
  83 + throw exception(STUDENT_NOT_EXISTS);
  84 + }
  85 + }
  86 +
  87 + @Override
  88 + public InfraStudentDO getStudent(Long id) {
  89 + return studentMapper.selectById(id);
  90 + }
  91 +
  92 + @Override
  93 + public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) {
  94 + return studentMapper.selectPage(pageReqVO);
  95 + }
  96 +
  97 + // ==================== 子表(学生联系人) ====================
  98 +
  99 + @Override
  100 + public List<InfraStudentContactDO> getStudentContactListByStudentId(Long studentId) {
  101 + return studentContactMapper.selectListByStudentId(studentId);
  102 + }
  103 +
  104 + private void createStudentContactList(Long studentId, List<InfraStudentContactDO> list) {
  105 + list.forEach(o -> o.setStudentId(studentId));
  106 + studentContactMapper.insertBatch(list);
  107 + }
  108 +
  109 + private void updateStudentContactList(Long studentId, List<InfraStudentContactDO> list) {
  110 + deleteStudentContactByStudentId(studentId);
  111 + list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新
  112 + createStudentContactList(studentId, list);
  113 + }
  114 +
  115 + private void deleteStudentContactByStudentId(Long studentId) {
  116 + studentContactMapper.deleteByStudentId(studentId);
  117 + }
  118 +
  119 + // ==================== 子表(学生班主任) ====================
  120 +
  121 + @Override
  122 + public InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId) {
  123 + return studentTeacherMapper.selectByStudentId(studentId);
  124 + }
  125 +
  126 + private void createStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) {
  127 + if (studentTeacher == null) {
  128 + return;
  129 + }
  130 + studentTeacher.setStudentId(studentId);
  131 + studentTeacherMapper.insert(studentTeacher);
  132 + }
  133 +
  134 + private void updateStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) {
  135 + if (studentTeacher == null) {
  136 + return;
  137 + }
  138 + studentTeacher.setStudentId(studentId);
  139 + studentTeacher.setUpdater(null).setUpdateTime(null); // 解决更新情况下:updateTime 不更新
  140 + studentTeacherMapper.insertOrUpdate(studentTeacher);
  141 + }
  142 +
  143 + private void deleteStudentTeacherByStudentId(Long studentId) {
  144 + studentTeacherMapper.deleteByStudentId(studentId);
  145 + }
  146 +
  147 +}
0 \ No newline at end of file 148 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentServiceImplTest 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.service.demo;
  2 +
  3 +import org.junit.jupiter.api.Disabled;
  4 +import org.junit.jupiter.api.Test;
  5 +import org.springframework.boot.test.mock.mockito.MockBean;
  6 +
  7 +import javax.annotation.Resource;
  8 +
  9 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  10 +
  11 +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
  12 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
  13 +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
  14 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  15 +
  16 +import javax.annotation.Resource;
  17 +import org.springframework.context.annotation.Import;
  18 +import java.util.*;
  19 +import java.time.LocalDateTime;
  20 +
  21 +import static cn.hutool.core.util.RandomUtil.*;
  22 +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
  23 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
  24 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
  25 +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
  26 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
  27 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
  28 +import static org.junit.jupiter.api.Assertions.*;
  29 +import static org.mockito.Mockito.*;
  30 +
  31 +/**
  32 + * {@link InfraStudentServiceImpl} 的单元测试类
  33 + *
  34 + * @author 芋道源码
  35 + */
  36 +@Import(InfraStudentServiceImpl.class)
  37 +public class InfraStudentServiceImplTest extends BaseDbUnitTest {
  38 +
  39 + @Resource
  40 + private InfraStudentServiceImpl studentService;
  41 +
  42 + @Resource
  43 + private InfraStudentMapper studentMapper;
  44 +
  45 + @Test
  46 + public void testCreateStudent_success() {
  47 + // 准备参数
  48 + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null);
  49 +
  50 + // 调用
  51 + Long studentId = studentService.createStudent(createReqVO);
  52 + // 断言
  53 + assertNotNull(studentId);
  54 + // 校验记录的属性是否正确
  55 + InfraStudentDO student = studentMapper.selectById(studentId);
  56 + assertPojoEquals(createReqVO, student, "id");
  57 + }
  58 +
  59 + @Test
  60 + public void testUpdateStudent_success() {
  61 + // mock 数据
  62 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
  63 + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
  64 + // 准备参数
  65 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> {
  66 + o.setId(dbStudent.getId()); // 设置更新的 ID
  67 + });
  68 +
  69 + // 调用
  70 + studentService.updateStudent(updateReqVO);
  71 + // 校验是否更新正确
  72 + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的
  73 + assertPojoEquals(updateReqVO, student);
  74 + }
  75 +
  76 + @Test
  77 + public void testUpdateStudent_notExists() {
  78 + // 准备参数
  79 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class);
  80 +
  81 + // 调用, 并断言异常
  82 + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS);
  83 + }
  84 +
  85 + @Test
  86 + public void testDeleteStudent_success() {
  87 + // mock 数据
  88 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
  89 + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
  90 + // 准备参数
  91 + Long id = dbStudent.getId();
  92 +
  93 + // 调用
  94 + studentService.deleteStudent(id);
  95 + // 校验数据不存在了
  96 + assertNull(studentMapper.selectById(id));
  97 + }
  98 +
  99 + @Test
  100 + public void testDeleteStudent_notExists() {
  101 + // 准备参数
  102 + Long id = randomLongId();
  103 +
  104 + // 调用, 并断言异常
  105 + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS);
  106 + }
  107 +
  108 + @Test
  109 + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
  110 + public void testGetStudentPage() {
  111 + // mock 数据
  112 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到
  113 + o.setName(null);
  114 + o.setBirthday(null);
  115 + o.setSex(null);
  116 + o.setEnabled(null);
  117 + o.setCreateTime(null);
  118 + });
  119 + studentMapper.insert(dbStudent);
  120 + // 测试 name 不匹配
  121 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null)));
  122 + // 测试 birthday 不匹配
  123 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null)));
  124 + // 测试 sex 不匹配
  125 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null)));
  126 + // 测试 enabled 不匹配
  127 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null)));
  128 + // 测试 createTime 不匹配
  129 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null)));
  130 + // 准备参数
  131 + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO();
  132 + reqVO.setName(null);
  133 + reqVO.setBirthday(null);
  134 + reqVO.setSex(null);
  135 + reqVO.setEnabled(null);
  136 + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
  137 +
  138 + // 调用
  139 + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(reqVO);
  140 + // 断言
  141 + assertEquals(1, pageResult.getTotal());
  142 + assertEquals(1, pageResult.getList().size());
  143 + assertPojoEquals(dbStudent, pageResult.getList().get(0));
  144 + }
  145 +
  146 +}
0 \ No newline at end of file 147 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentTeacherDO 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import java.time.LocalDateTime;
  6 +import java.time.LocalDateTime;
  7 +import com.baomidou.mybatisplus.annotation.*;
  8 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  9 +
  10 +/**
  11 + * 学生班主任 DO
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@TableName("infra_student_teacher")
  16 +@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class InfraStudentTeacherDO extends BaseDO {
  24 +
  25 + /**
  26 + * 编号
  27 + */
  28 + @TableId
  29 + private Long id;
  30 + /**
  31 + * 学生编号
  32 + */
  33 + private Long studentId;
  34 + /**
  35 + * 名字
  36 + */
  37 + private String name;
  38 + /**
  39 + * 简介
  40 + */
  41 + private String description;
  42 + /**
  43 + * 出生日期
  44 + */
  45 + private LocalDateTime birthday;
  46 + /**
  47 + * 性别
  48 + *
  49 + * 枚举 {@link TODO system_user_sex 对应的类}
  50 + */
  51 + private Integer sex;
  52 + /**
  53 + * 是否有效
  54 + *
  55 + * 枚举 {@link TODO infra_boolean_string 对应的类}
  56 + */
  57 + private Boolean enabled;
  58 + /**
  59 + * 头像
  60 + */
  61 + private String avatar;
  62 + /**
  63 + * 附件
  64 + */
  65 + private String video;
  66 + /**
  67 + * 备注
  68 + */
  69 + private String memo;
  70 +
  71 +}
0 \ No newline at end of file 72 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentTeacherMapper 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.dal.mysql.demo;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  8 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  9 +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
  10 +import org.apache.ibatis.annotations.Mapper;
  11 +
  12 +/**
  13 + * 学生班主任 Mapper
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Mapper
  18 +public interface InfraStudentTeacherMapper extends BaseMapperX<InfraStudentTeacherDO> {
  19 +
  20 + default InfraStudentTeacherDO selectByStudentId(Long studentId) {
  21 + return selectOne(InfraStudentTeacherDO::getStudentId, studentId);
  22 + }
  23 +
  24 + default int deleteByStudentId(Long studentId) {
  25 + return delete(InfraStudentTeacherDO::getStudentId, studentId);
  26 + }
  27 +
  28 +}
0 \ No newline at end of file 29 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/sql/h2 0 → 100644
  1 +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里
  2 +CREATE TABLE IF NOT EXISTS "infra_student" (
  3 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  4 + "name" varchar NOT NULL,
  5 + "description" varchar NOT NULL,
  6 + "birthday" varchar NOT NULL,
  7 + "sex" int NOT NULL,
  8 + "enabled" bit NOT NULL,
  9 + "avatar" varchar NOT NULL,
  10 + "video" varchar NOT NULL,
  11 + "memo" varchar NOT NULL,
  12 + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  13 + PRIMARY KEY ("id")
  14 +) COMMENT '学生表';
  15 +
  16 +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里
  17 +DELETE FROM "infra_student";
0 \ No newline at end of file 18 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/sql/sql 0 → 100644
  1 +-- 菜单 SQL
  2 +INSERT INTO system_menu(
  3 + name, permission, type, sort, parent_id,
  4 + path, icon, component, status, component_name
  5 +)
  6 +VALUES (
  7 + '学生管理', '', 2, 0, 888,
  8 + 'student', '', 'infra/demo/index', 0, 'InfraStudent'
  9 +);
  10 +
  11 +-- 按钮父菜单ID
  12 +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
  13 +SELECT @parentId := LAST_INSERT_ID();
  14 +
  15 +-- 按钮 SQL
  16 +INSERT INTO system_menu(
  17 + name, permission, type, sort, parent_id,
  18 + path, icon, component, status
  19 +)
  20 +VALUES (
  21 + '学生查询', 'infra:student:query', 3, 1, @parentId,
  22 + '', '', '', 0
  23 +);
  24 +INSERT INTO system_menu(
  25 + name, permission, type, sort, parent_id,
  26 + path, icon, component, status
  27 +)
  28 +VALUES (
  29 + '学生创建', 'infra:student:create', 3, 2, @parentId,
  30 + '', '', '', 0
  31 +);
  32 +INSERT INTO system_menu(
  33 + name, permission, type, sort, parent_id,
  34 + path, icon, component, status
  35 +)
  36 +VALUES (
  37 + '学生更新', 'infra:student:update', 3, 3, @parentId,
  38 + '', '', '', 0
  39 +);
  40 +INSERT INTO system_menu(
  41 + name, permission, type, sort, parent_id,
  42 + path, icon, component, status
  43 +)
  44 +VALUES (
  45 + '学生删除', 'infra:student:delete', 3, 4, @parentId,
  46 + '', '', '', 0
  47 +);
  48 +INSERT INTO system_menu(
  49 + name, permission, type, sort, parent_id,
  50 + path, icon, component, status
  51 +)
  52 +VALUES (
  53 + '学生导出', 'infra:student:export', 3, 5, @parentId,
  54 + '', '', '', 0
  55 +);
0 \ No newline at end of file 56 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/ts/index 0 → 100644
  1 +import request from '@/config/axios'
  2 +
  3 +export interface StudentVO {
  4 + id: number
  5 + name: string
  6 + description: string
  7 + birthday: Date
  8 + sex: number
  9 + enabled: boolean
  10 + avatar: string
  11 + video: string
  12 + memo: string
  13 +}
  14 +
  15 +// 查询学生分页
  16 +export const getStudentPage = async (params) => {
  17 + return await request.get({ url: `/infra/student/page`, params })
  18 +}
  19 +
  20 +// 查询学生详情
  21 +export const getStudent = async (id: number) => {
  22 + return await request.get({ url: `/infra/student/get?id=` + id })
  23 +}
  24 +
  25 +// 新增学生
  26 +export const createStudent = async (data: StudentVO) => {
  27 + return await request.post({ url: `/infra/student/create`, data })
  28 +}
  29 +
  30 +// 修改学生
  31 +export const updateStudent = async (data: StudentVO) => {
  32 + return await request.put({ url: `/infra/student/update`, data })
  33 +}
  34 +
  35 +// 删除学生
  36 +export const deleteStudent = async (id: number) => {
  37 + return await request.delete({ url: `/infra/student/delete?id=` + id })
  38 +}
  39 +
  40 +// 导出学生 Excel
  41 +export const exportStudent = async (params) => {
  42 + return await request.download({ url: `/infra/student/export-excel`, params })
  43 +}
  44 +
  45 +// ==================== 子表(学生联系人) ====================
  46 +
  47 +// 获得学生联系人列表
  48 +export const getStudentContactListByStudentId = async (studentId) => {
  49 + return await request.get({ url: `/infra/student/student-contact/list-by-student-id?studentId=` + studentId })
  50 +}
  51 +
  52 +// ==================== 子表(学生班主任) ====================
  53 +
  54 +// 获得学生班主任
  55 +export const getStudentTeacherByStudentId = async (studentId) => {
  56 + return await request.get({ url: `/infra/student/student-teacher/get-by-student-id?studentId=` + studentId })
  57 +}
0 \ No newline at end of file 58 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/StudentContactForm 0 → 100644
  1 +<template>
  2 + <el-form
  3 + ref="formRef"
  4 + :model="formData"
  5 + :rules="formRules"
  6 + v-loading="formLoading"
  7 + label-width="0px"
  8 + :inline-message="true"
  9 + >
  10 + <el-table :data="formData" class="-mt-10px">
  11 + <el-table-column label="序号" type="index" width="100" />
  12 + <el-table-column label="名字" min-width="150">
  13 + <template #default="{ row, $index }">
  14 + <el-form-item :prop="`${$index}.name`" :rules="formRules.name" class="mb-0px!">
  15 + <el-input v-model="row.name" placeholder="请输入名字" />
  16 + </el-form-item>
  17 + </template>
  18 + </el-table-column>
  19 + <el-table-column label="简介" min-width="200">
  20 + <template #default="{ row, $index }">
  21 + <el-form-item :prop="`${$index}.description`" :rules="formRules.description" class="mb-0px!">
  22 + <el-input v-model="row.description" type="textarea" placeholder="请输入简介" />
  23 + </el-form-item>
  24 + </template>
  25 + </el-table-column>
  26 + <el-table-column label="出生日期" min-width="150">
  27 + <template #default="{ row, $index }">
  28 + <el-form-item :prop="`${$index}.birthday`" :rules="formRules.birthday" class="mb-0px!">
  29 + <el-date-picker
  30 + v-model="row.birthday"
  31 + type="date"
  32 + value-format="x"
  33 + placeholder="选择出生日期"
  34 + />
  35 + </el-form-item>
  36 + </template>
  37 + </el-table-column>
  38 + <el-table-column label="性别" min-width="150">
  39 + <template #default="{ row, $index }">
  40 + <el-form-item :prop="`${$index}.sex`" :rules="formRules.sex" class="mb-0px!">
  41 + <el-select v-model="row.sex" placeholder="请选择性别">
  42 + <el-option
  43 + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
  44 + :key="dict.value"
  45 + :label="dict.label"
  46 + :value="dict.value"
  47 + />
  48 + </el-select>
  49 + </el-form-item>
  50 + </template>
  51 + </el-table-column>
  52 + <el-table-column label="是否有效" min-width="150">
  53 + <template #default="{ row, $index }">
  54 + <el-form-item :prop="`${$index}.enabled`" :rules="formRules.enabled" class="mb-0px!">
  55 + <el-radio-group v-model="row.enabled">
  56 + <el-radio
  57 + v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
  58 + :key="dict.value"
  59 + :label="dict.value"
  60 + >
  61 + {{ dict.label }}
  62 + </el-radio>
  63 + </el-radio-group>
  64 + </el-form-item>
  65 + </template>
  66 + </el-table-column>
  67 + <el-table-column label="头像" min-width="200">
  68 + <template #default="{ row, $index }">
  69 + <el-form-item :prop="`${$index}.avatar`" :rules="formRules.avatar" class="mb-0px!">
  70 + <UploadImg v-model="row.avatar" />
  71 + </el-form-item>
  72 + </template>
  73 + </el-table-column>
  74 + <el-table-column label="附件" min-width="200">
  75 + <template #default="{ row, $index }">
  76 + <el-form-item :prop="`${$index}.video`" :rules="formRules.video" class="mb-0px!">
  77 + <UploadFile v-model="row.video" />
  78 + </el-form-item>
  79 + </template>
  80 + </el-table-column>
  81 + <el-table-column label="备注" min-width="400">
  82 + <template #default="{ row, $index }">
  83 + <el-form-item :prop="`${$index}.memo`" :rules="formRules.memo" class="mb-0px!">
  84 + <Editor v-model="row.memo" height="150px" />
  85 + </el-form-item>
  86 + </template>
  87 + </el-table-column>
  88 + <el-table-column align="center" fixed="right" label="操作" width="60">
  89 + <template #default="{ $index }">
  90 + <el-button @click="handleDelete($index)" link>—</el-button>
  91 + </template>
  92 + </el-table-column>
  93 + </el-table>
  94 + </el-form>
  95 + <el-row justify="center" class="mt-3">
  96 + <el-button @click="handleAdd" round>+ 添加学生联系人</el-button>
  97 + </el-row>
  98 +</template>
  99 +<script setup lang="ts">
  100 +import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
  101 +import * as StudentApi from '@/api/infra/demo'
  102 +
  103 +const props = defineProps<{
  104 + studentId: undefined // 学生编号(主表的关联字段)
  105 +}>()
  106 +const formLoading = ref(false) // 表单的加载中
  107 +const formData = ref([])
  108 +const formRules = reactive({
  109 + studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
  110 + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
  111 + description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
  112 + birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
  113 + sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
  114 + enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
  115 + avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
  116 + memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
  117 +})
  118 +const formRef = ref() // 表单 Ref
  119 +
  120 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  121 +watch(
  122 + () => props.studentId,
  123 + async (val) => {
  124 + // 1. 重置表单
  125 + formData.value = []
  126 + // 2. val 非空,则加载数据
  127 + if (!val) {
  128 + return;
  129 + }
  130 + try {
  131 + formLoading.value = true
  132 + formData.value = await StudentApi.getStudentContactListByStudentId(val)
  133 + } finally {
  134 + formLoading.value = false
  135 + }
  136 + },
  137 + { immediate: true }
  138 +)
  139 +
  140 +/** 新增按钮操作 */
  141 +const handleAdd = () => {
  142 + const row = {
  143 + id: undefined,
  144 + studentId: undefined,
  145 + name: undefined,
  146 + description: undefined,
  147 + birthday: undefined,
  148 + sex: undefined,
  149 + enabled: undefined,
  150 + avatar: undefined,
  151 + video: undefined,
  152 + memo: undefined
  153 + }
  154 + row.studentId = props.studentId
  155 + formData.value.push(row)
  156 +}
  157 +
  158 +/** 删除按钮操作 */
  159 +const handleDelete = (index) => {
  160 + formData.value.splice(index, 1)
  161 +}
  162 +
  163 +/** 表单校验 */
  164 +const validate = () => {
  165 + return formRef.value.validate()
  166 +}
  167 +
  168 +/** 表单值 */
  169 +const getData = () => {
  170 + return formData.value
  171 +}
  172 +
  173 +defineExpose({ validate, getData })
  174 +</script>
0 \ No newline at end of file 175 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/StudentForm 0 → 100644
  1 +<template>
  2 + <Dialog :title="dialogTitle" v-model="dialogVisible">
  3 + <el-form
  4 + ref="formRef"
  5 + :model="formData"
  6 + :rules="formRules"
  7 + label-width="100px"
  8 + v-loading="formLoading"
  9 + >
  10 + <el-form-item label="名字" prop="name">
  11 + <el-input v-model="formData.name" placeholder="请输入名字" />
  12 + </el-form-item>
  13 + <el-form-item label="简介" prop="description">
  14 + <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
  15 + </el-form-item>
  16 + <el-form-item label="出生日期" prop="birthday">
  17 + <el-date-picker
  18 + v-model="formData.birthday"
  19 + type="date"
  20 + value-format="x"
  21 + placeholder="选择出生日期"
  22 + />
  23 + </el-form-item>
  24 + <el-form-item label="性别" prop="sex">
  25 + <el-select v-model="formData.sex" placeholder="请选择性别">
  26 + <el-option
  27 + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
  28 + :key="dict.value"
  29 + :label="dict.label"
  30 + :value="dict.value"
  31 + />
  32 + </el-select>
  33 + </el-form-item>
  34 + <el-form-item label="是否有效" prop="enabled">
  35 + <el-radio-group v-model="formData.enabled">
  36 + <el-radio
  37 + v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
  38 + :key="dict.value"
  39 + :label="dict.value"
  40 + >
  41 + {{ dict.label }}
  42 + </el-radio>
  43 + </el-radio-group>
  44 + </el-form-item>
  45 + <el-form-item label="头像" prop="avatar">
  46 + <UploadImg v-model="formData.avatar" />
  47 + </el-form-item>
  48 + <el-form-item label="附件" prop="video">
  49 + <UploadFile v-model="formData.video" />
  50 + </el-form-item>
  51 + <el-form-item label="备注" prop="memo">
  52 + <Editor v-model="formData.memo" height="150px" />
  53 + </el-form-item>
  54 + </el-form>
  55 + <!-- 子表的表单 -->
  56 + <el-tabs v-model="subTabsName">
  57 + <el-tab-pane label="学生联系人" name="studentContact">
  58 + <StudentContactForm ref="studentContactFormRef" :student-id="formData.id" />
  59 + </el-tab-pane>
  60 + <el-tab-pane label="学生班主任" name="studentTeacher">
  61 + <StudentTeacherForm ref="studentTeacherFormRef" :student-id="formData.id" />
  62 + </el-tab-pane>
  63 + </el-tabs>
  64 + <template #footer>
  65 + <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
  66 + <el-button @click="dialogVisible = false">取 消</el-button>
  67 + </template>
  68 + </Dialog>
  69 +</template>
  70 +<script setup lang="ts">
  71 +import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
  72 +import * as StudentApi from '@/api/infra/demo'
  73 +import StudentContactForm from './components/StudentContactForm.vue'
  74 +import StudentTeacherForm from './components/StudentTeacherForm.vue'
  75 +
  76 +const { t } = useI18n() // 国际化
  77 +const message = useMessage() // 消息弹窗
  78 +
  79 +const dialogVisible = ref(false) // 弹窗的是否展示
  80 +const dialogTitle = ref('') // 弹窗的标题
  81 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  82 +const formType = ref('') // 表单的类型:create - 新增;update - 修改
  83 +const formData = ref({
  84 + id: undefined,
  85 + name: undefined,
  86 + description: undefined,
  87 + birthday: undefined,
  88 + sex: undefined,
  89 + enabled: undefined,
  90 + avatar: undefined,
  91 + video: undefined,
  92 + memo: undefined
  93 +})
  94 +const formRules = reactive({
  95 + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
  96 + description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
  97 + birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
  98 + sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
  99 + enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
  100 + avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
  101 + video: [{ required: true, message: '附件不能为空', trigger: 'blur' }],
  102 + memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
  103 +})
  104 +const formRef = ref() // 表单 Ref
  105 +
  106 +/** 子表的表单 */
  107 +const subTabsName = ref('studentContact')
  108 +const studentContactFormRef = ref()
  109 +const studentTeacherFormRef = ref()
  110 +
  111 +/** 打开弹窗 */
  112 +const open = async (type: string, id?: number) => {
  113 + dialogVisible.value = true
  114 + dialogTitle.value = t('action.' + type)
  115 + formType.value = type
  116 + resetForm()
  117 + // 修改时,设置数据
  118 + if (id) {
  119 + formLoading.value = true
  120 + try {
  121 + formData.value = await StudentApi.getStudent(id)
  122 + } finally {
  123 + formLoading.value = false
  124 + }
  125 + }
  126 +}
  127 +defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  128 +
  129 +/** 提交表单 */
  130 +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  131 +const submitForm = async () => {
  132 + // 校验表单
  133 + await formRef.value.validate()
  134 + // 校验子表单
  135 + try {
  136 + await studentContactFormRef.value.validate()
  137 + } catch (e) {
  138 + subTabsName.value = 'studentContact'
  139 + return
  140 + }
  141 + try {
  142 + await studentTeacherFormRef.value.validate()
  143 + } catch (e) {
  144 + subTabsName.value = 'studentTeacher'
  145 + return
  146 + }
  147 + // 提交请求
  148 + formLoading.value = true
  149 + try {
  150 + const data = formData.value as unknown as StudentApi.StudentVO
  151 + // 拼接子表的数据
  152 + data.studentContacts = studentContactFormRef.value.getData()
  153 + data.studentTeacher = studentTeacherFormRef.value.getData()
  154 + if (formType.value === 'create') {
  155 + await StudentApi.createStudent(data)
  156 + message.success(t('common.createSuccess'))
  157 + } else {
  158 + await StudentApi.updateStudent(data)
  159 + message.success(t('common.updateSuccess'))
  160 + }
  161 + dialogVisible.value = false
  162 + // 发送操作成功的事件
  163 + emit('success')
  164 + } finally {
  165 + formLoading.value = false
  166 + }
  167 +}
  168 +
  169 +/** 重置表单 */
  170 +const resetForm = () => {
  171 + formData.value = {
  172 + id: undefined,
  173 + name: undefined,
  174 + description: undefined,
  175 + birthday: undefined,
  176 + sex: undefined,
  177 + enabled: undefined,
  178 + avatar: undefined,
  179 + video: undefined,
  180 + memo: undefined
  181 + }
  182 + formRef.value?.resetFields()
  183 +}
  184 +</script>
0 \ No newline at end of file 185 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/StudentTeacherForm 0 → 100644
  1 +<template>
  2 + <el-form
  3 + ref="formRef"
  4 + :model="formData"
  5 + :rules="formRules"
  6 + label-width="100px"
  7 + v-loading="formLoading"
  8 + >
  9 + <el-form-item label="名字" prop="name">
  10 + <el-input v-model="formData.name" placeholder="请输入名字" />
  11 + </el-form-item>
  12 + <el-form-item label="简介" prop="description">
  13 + <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
  14 + </el-form-item>
  15 + <el-form-item label="出生日期" prop="birthday">
  16 + <el-date-picker
  17 + v-model="formData.birthday"
  18 + type="date"
  19 + value-format="x"
  20 + placeholder="选择出生日期"
  21 + />
  22 + </el-form-item>
  23 + <el-form-item label="性别" prop="sex">
  24 + <el-select v-model="formData.sex" placeholder="请选择性别">
  25 + <el-option
  26 + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
  27 + :key="dict.value"
  28 + :label="dict.label"
  29 + :value="dict.value"
  30 + />
  31 + </el-select>
  32 + </el-form-item>
  33 + <el-form-item label="是否有效" prop="enabled">
  34 + <el-radio-group v-model="formData.enabled">
  35 + <el-radio
  36 + v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
  37 + :key="dict.value"
  38 + :label="dict.value"
  39 + >
  40 + {{ dict.label }}
  41 + </el-radio>
  42 + </el-radio-group>
  43 + </el-form-item>
  44 + <el-form-item label="头像" prop="avatar">
  45 + <UploadImg v-model="formData.avatar" />
  46 + </el-form-item>
  47 + <el-form-item label="附件" prop="video">
  48 + <UploadFile v-model="formData.video" />
  49 + </el-form-item>
  50 + <el-form-item label="备注" prop="memo">
  51 + <Editor v-model="formData.memo" height="150px" />
  52 + </el-form-item>
  53 + </el-form>
  54 +</template>
  55 +<script setup lang="ts">
  56 +import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
  57 +import * as StudentApi from '@/api/infra/demo'
  58 +
  59 +const props = defineProps<{
  60 + studentId: undefined // 学生编号(主表的关联字段)
  61 +}>()
  62 +const formLoading = ref(false) // 表单的加载中
  63 +const formData = ref([])
  64 +const formRules = reactive({
  65 + studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
  66 + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
  67 + description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
  68 + birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
  69 + sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
  70 + enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
  71 + avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
  72 + memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
  73 +})
  74 +const formRef = ref() // 表单 Ref
  75 +
  76 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  77 +watch(
  78 + () => props.studentId,
  79 + async (val) => {
  80 + // 1. 重置表单
  81 + formData.value = {
  82 + id: undefined,
  83 + studentId: undefined,
  84 + name: undefined,
  85 + description: undefined,
  86 + birthday: undefined,
  87 + sex: undefined,
  88 + enabled: undefined,
  89 + avatar: undefined,
  90 + video: undefined,
  91 + memo: undefined,
  92 + }
  93 + // 2. val 非空,则加载数据
  94 + if (!val) {
  95 + return;
  96 + }
  97 + try {
  98 + formLoading.value = true
  99 + const data = await StudentApi.getStudentTeacherByStudentId(val)
  100 + if (!data) {
  101 + return
  102 + }
  103 + formData.value = data
  104 + } finally {
  105 + formLoading.value = false
  106 + }
  107 + },
  108 + { immediate: true }
  109 +)
  110 +
  111 +/** 表单校验 */
  112 +const validate = () => {
  113 + return formRef.value.validate()
  114 +}
  115 +
  116 +/** 表单值 */
  117 +const getData = () => {
  118 + return formData.value
  119 +}
  120 +
  121 +defineExpose({ validate, getData })
  122 +</script>
0 \ No newline at end of file 123 \ No newline at end of file