代码生成器:增加单元测试,🛫
This commit is contained in:
parent
ee918a6d3f
commit
067d53ac48
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.json;
|
|||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
@ -30,6 +31,7 @@ public class JsonUtils {
|
|||
static {
|
||||
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略 null 值
|
||||
objectMapper.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化
|
||||
}
|
||||
|
||||
|
@ -71,6 +73,20 @@ public class JsonUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static <T> T parseObject(String text, String path, Class<T> clazz) {
|
||||
if (StrUtil.isEmpty(text)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
JsonNode treeNode = objectMapper.readTree(text);
|
||||
JsonNode pathNode = treeNode.path(path);
|
||||
return objectMapper.readValue(pathNode.toString(), clazz);
|
||||
} catch (IOException e) {
|
||||
log.error("json parse err,json:{}", text, e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T parseObject(String text, Type type) {
|
||||
if (StrUtil.isEmpty(text)) {
|
||||
return null;
|
||||
|
@ -132,6 +148,20 @@ public class JsonUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static <T> List<T> parseArray(String text, String path, Class<T> clazz) {
|
||||
if (StrUtil.isEmpty(text)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
JsonNode treeNode = objectMapper.readTree(text);
|
||||
JsonNode pathNode = treeNode.path(path);
|
||||
return objectMapper.readValue(pathNode.toString(), objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
|
||||
} catch (IOException e) {
|
||||
log.error("json parse err,json:{}", text, e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static JsonNode parseTree(String text) {
|
||||
try {
|
||||
return objectMapper.readTree(text);
|
||||
|
|
|
@ -49,13 +49,14 @@ public class ${sceneEnum.prefixClass}${table.className}SaveReqVO {
|
|||
#end
|
||||
## 特殊:主子表专属逻辑(非 ERP 模式)
|
||||
#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
|
||||
|
||||
#foreach ($subTable in $subTables)
|
||||
#set ($index = $foreach.count - 1)
|
||||
#if ( $subTable.subJoinMany)
|
||||
@Schema(description = "${subTable.classComment}列表")
|
||||
private List<${subTable.className}DO> ${subClassNameVars.get($index)}s;
|
||||
|
||||
#else
|
||||
@Schema(description = "${subTable.classComment}")
|
||||
private ${subTable.className}DO ${subClassNameVars.get($index)};
|
||||
|
||||
#end
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
|
||||
|
||||
import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaColumnDO;
|
||||
import cn.iocoder.yudao.module.tool.test.BaseDbUnitTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class SchemaColumnMapperTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private SchemaColumnMapper schemaColumnMapper;
|
||||
|
||||
@Test
|
||||
public void testSelectListByTableName() {
|
||||
List<SchemaColumnDO> columns = schemaColumnMapper.selectListByTableName("", "inf_config");
|
||||
assertTrue(columns.size() > 0);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* 占位
|
||||
*/
|
||||
package cn.iocoder.yudao.module.infra.dal.mysql;
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* 占位
|
||||
*/
|
||||
package cn.iocoder.yudao.module.infra.dal;
|
|
@ -1,34 +0,0 @@
|
|||
package cn.iocoder.yudao.module.infra.service.codegen;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper;
|
||||
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine;
|
||||
import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CodegenEngineTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private CodegenTableMapper codegenTableMapper;
|
||||
@Resource
|
||||
private CodegenColumnMapper codegenColumnMapper;
|
||||
|
||||
@Resource
|
||||
private CodegenEngine codegenEngine;
|
||||
|
||||
@Test
|
||||
public void testExecute() {
|
||||
CodegenTableDO table = codegenTableMapper.selectById(20);
|
||||
List<CodegenColumnDO> columns = codegenColumnMapper.selectListByTableId(table.getId());
|
||||
Map<String, String> result = codegenEngine.execute(table, columns);
|
||||
result.forEach((s, s2) -> System.out.println(s2));
|
||||
// System.out.println(result.get("vue/views/system/test/index.vue"));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package cn.iocoder.yudao.module.infra.service.codegen;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenSQLParser;
|
||||
import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class CodegenSQLParserTest extends BaseDbUnitTest {
|
||||
|
||||
@Test
|
||||
public void testParse() {
|
||||
String sql = "CREATE TABLE `infra_test_demo` (\n" +
|
||||
" `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',\n" +
|
||||
" `name` varchar(100) NOT NULL DEFAULT '' COMMENT '名字',\n" +
|
||||
" `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态',\n" +
|
||||
" `type` tinyint(4) NOT NULL COMMENT '类型',\n" +
|
||||
" `category` tinyint(4) NOT NULL COMMENT '分类',\n" +
|
||||
" `remark` varchar(500) DEFAULT NULL COMMENT '备注',\n" +
|
||||
" `create_by` varchar(64) DEFAULT '' COMMENT '创建者',\n" +
|
||||
" `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n" +
|
||||
" `update_by` varchar(64) DEFAULT '' COMMENT '更新者',\n" +
|
||||
" `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n" +
|
||||
" `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',\n" +
|
||||
" PRIMARY KEY (`id`) USING BTREE\n" +
|
||||
") ENGINE=InnoDB AUTO_INCREMENT=108 DEFAULT CHARSET=utf8mb4 COMMENT='字典类型表';";
|
||||
CodegenSQLParser.parse(sql);
|
||||
// TODO 芋艿:后续完善断言
|
||||
}
|
||||
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package cn.iocoder.yudao.module.infra.service.codegen;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
class CodegenServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private CodegenServiceImpl codegenService;
|
||||
|
||||
@Test
|
||||
public void tetCreateCodegenTable() {
|
||||
codegenService.createCodegen(0L, "infra_test_demo");
|
||||
// infraCodegenService.createCodegenTable("infra_codegen_table");
|
||||
// infraCodegenService.createCodegen("infra_codegen_column");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* 占位
|
||||
*/
|
||||
package cn.iocoder.yudao.module.infra.service;
|
|
@ -1,38 +0,0 @@
|
|||
package cn.iocoder.yudao.module.infra.test;
|
||||
|
||||
import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
|
||||
import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
|
||||
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
|
||||
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
||||
import org.redisson.spring.starter.RedissonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisIntegrationTest.Application.class)
|
||||
@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件
|
||||
public class BaseDbAndRedisIntegrationTest {
|
||||
|
||||
@Import({
|
||||
// DB 配置类
|
||||
DynamicDataSourceAutoConfiguration.class, // Dynamic Datasource 配置类
|
||||
YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类
|
||||
DataSourceAutoConfiguration.class, // Spring DB 自动配置类
|
||||
DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
|
||||
// MyBatis 配置类
|
||||
YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
|
||||
MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
|
||||
|
||||
// Redis 配置类
|
||||
RedisAutoConfiguration.class, // Spring Redis 自动配置类
|
||||
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
|
||||
RedissonAutoConfiguration.class, // Redisson 自动高配置类
|
||||
})
|
||||
public static class Application {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package cn.iocoder.yudao.module.infra.test;
|
||||
|
||||
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
||||
import org.redisson.spring.starter.RedissonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseRedisIntegrationTest.Application.class)
|
||||
@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件
|
||||
public class BaseRedisIntegrationTest {
|
||||
|
||||
@Import({
|
||||
// Redis 配置类
|
||||
RedisAutoConfiguration.class, // Spring Redis 自动配置类
|
||||
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
|
||||
RedissonAutoConfiguration.class, // Redisson 自动高配置类
|
||||
})
|
||||
public static class Application {
|
||||
}
|
||||
|
||||
}
|
|
@ -3,7 +3,10 @@ package cn.iocoder.yudao.module.infra.service.codegen.inner;
|
|||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
|
@ -17,11 +20,10 @@ import org.mockito.Spy;
|
|||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* {@link CodegenEngine} 的单元测试
|
||||
|
@ -42,760 +44,127 @@ public class CodegenEngineTest extends BaseMockitoUnitTest {
|
|||
codegenEngine.initGlobalBindingMap();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute_vue3_one() {
|
||||
// 准备参数
|
||||
CodegenTableDO table = getTable("student")
|
||||
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
|
||||
.setTemplateType(CodegenTemplateTypeEnum.ONE.getType());
|
||||
List<CodegenColumnDO> columns = getColumnList("student");
|
||||
|
||||
// 调用
|
||||
Map<String, String> result = codegenEngine.execute(table, columns, null, null);
|
||||
// 断言
|
||||
assertResult(result, "codegen/vue3_one");
|
||||
// writeResult(result, "/root/ruoyi-vue-pro/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute_vue3_tree() {
|
||||
// 准备请求参数
|
||||
CodegenTableDO table = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene()).setParentMenuId(888L)
|
||||
.setTableName("infra_demo66_student").setTableComment("学生表")
|
||||
.setModuleName("infra").setBusinessName("demo66").setClassName("InfraDemo66Student")
|
||||
.setClassComment("学生").setAuthor("芋道源码")
|
||||
.setTemplateType(CodegenTemplateTypeEnum.TREE.getType())
|
||||
// 准备参数
|
||||
CodegenTableDO table = getTable("category")
|
||||
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
|
||||
.setTreeParentColumnId(22L).setTreeNameColumnId(11L);
|
||||
CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
|
||||
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
|
||||
.setJavaType("Long").setJavaField("id").setExample("1024")
|
||||
.setCreateOperation(false).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true);
|
||||
CodegenColumnDO nameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
|
||||
.setId(11L)
|
||||
.setColumnComment("名字").setNullable(false)
|
||||
.setJavaType("String").setJavaField("name").setExample("芋头")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
|
||||
CodegenColumnDO parentIdColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
|
||||
.setId(22L)
|
||||
.setColumnComment("父编号").setNullable(false)
|
||||
.setJavaType("Long").setJavaField("parentId").setExample("2048")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true);
|
||||
List<CodegenColumnDO> columns = Arrays.asList(idColumn, nameColumn, parentIdColumn);
|
||||
.setTemplateType(CodegenTemplateTypeEnum.TREE.getType());
|
||||
List<CodegenColumnDO> columns = getColumnList("category");
|
||||
|
||||
// 调用
|
||||
Map<String, String> result = codegenEngine.execute(table, columns, null, null);
|
||||
|
||||
// 构建 zip 包
|
||||
writeFile(result, "/Users/yunai/test/demo66.zip");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute_vue3_crud() {
|
||||
// 准备请求参数
|
||||
CodegenTableDO table = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene()).setParentMenuId(888L)
|
||||
.setTableName("infra_demo01_student").setTableComment("学生表")
|
||||
.setModuleName("infra").setBusinessName("demo01").setClassName("InfraDemo01Student")
|
||||
.setClassComment("学生").setAuthor("芋道源码")
|
||||
.setTemplateType(CodegenTemplateTypeEnum.ONE.getType())
|
||||
.setFrontType(CodegenFrontTypeEnum.VUE3.getType());
|
||||
CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
|
||||
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
|
||||
.setJavaType("Long").setJavaField("id").setExample("1024")
|
||||
.setCreateOperation(false).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true);
|
||||
CodegenColumnDO nameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("名字").setNullable(false)
|
||||
.setJavaType("String").setJavaField("name").setExample("芋头")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
|
||||
CodegenColumnDO descriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("简介").setNullable(false)
|
||||
.setJavaType("String").setJavaField("description").setExample("我是介绍")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
|
||||
CodegenColumnDO birthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("出生日期").setNullable(false)
|
||||
.setJavaType("LocalDateTime").setJavaField("birthday")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
CodegenColumnDO sexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
|
||||
.setColumnComment("性别").setNullable(false)
|
||||
.setJavaType("Integer").setJavaField("sex").setExample("1")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
|
||||
.setDictType("system_user_sex");
|
||||
CodegenColumnDO enabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
|
||||
.setColumnComment("是否有效").setNullable(false)
|
||||
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
|
||||
.setDictType("infra_boolean_string");
|
||||
CodegenColumnDO avatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("头像").setNullable(false)
|
||||
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
|
||||
CodegenColumnDO videoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("附件").setNullable(true)
|
||||
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
|
||||
CodegenColumnDO memoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("备注").setNullable(false)
|
||||
.setJavaType("String").setJavaField("memo").setExample("我是备注")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
|
||||
CodegenColumnDO createTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("创建时间").setNullable(true)
|
||||
.setJavaType("LocalDateTime").setJavaField("createTime")
|
||||
.setCreateOperation(false).setUpdateOperation(false)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
List<CodegenColumnDO> columns = Arrays.asList(idColumn, nameColumn, descriptionColumn, birthdayColumn,
|
||||
sexColumn, enabledColumn, avatarColumn, videoColumn, memoColumn, createTimeColumn);
|
||||
|
||||
// 调用
|
||||
Map<String, String> result = codegenEngine.execute(table, columns, null, null);
|
||||
|
||||
// 构建 zip 包
|
||||
writeFile(result, "/Users/yunai/test/demo01.zip");
|
||||
|
||||
// 断言
|
||||
assertEquals(21, result.size());
|
||||
// 断言 vo 类
|
||||
for (String vo : new String[]{"SystemUserBaseVO", "SystemUserCreateReqVO", "SystemUserUpdateReqVO", "SystemUserRespVO",
|
||||
"SystemUserPageReqVO", "SystemUserExportReqVO", "SystemUserExcelVO"}) {
|
||||
assertPathContentEquals("vue3_crud/java/" + vo,
|
||||
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/" + vo + ".java");
|
||||
}
|
||||
// 断言 controller 类
|
||||
assertPathContentEquals("vue3_crud/java/SystemUserController",
|
||||
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/SystemUserController.java");
|
||||
// 断言 service 类
|
||||
assertPathContentEquals("vue3_crud/java/SystemUserService",
|
||||
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/SystemUserService.java");
|
||||
assertPathContentEquals("vue3_crud/java/SystemUserServiceImpl",
|
||||
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/SystemUserServiceImpl.java");
|
||||
// 断言 convert 类
|
||||
assertPathContentEquals("vue3_crud/java/SystemUserConvert",
|
||||
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/user/SystemUserConvert.java");
|
||||
// 断言 enums 类
|
||||
assertPathContentEquals("vue3_crud/java/ErrorCodeConstants",
|
||||
result, "yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants_手动操作.java");
|
||||
// 断言 dal 类
|
||||
assertPathContentEquals("vue3_crud/java/SystemUserDO",
|
||||
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/SystemUserDO.java");
|
||||
assertPathContentEquals("vue3_crud/java/SystemUserMapper",
|
||||
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/SystemUserMapper.java");
|
||||
assertPathContentEquals("vue3_crud/java/SystemUserMapper_xml",
|
||||
result, "yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/user/SystemUserMapper.xml");
|
||||
// 断言 test 类
|
||||
assertPathContentEquals("vue3_crud/java/SystemUserServiceImplTest",
|
||||
result, "yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/SystemUserServiceImplTest.java");
|
||||
// 断言 sql 语句
|
||||
assertPathContentEquals("vue3_crud/sql/h2",
|
||||
result, "sql/h2.sql");
|
||||
assertPathContentEquals("vue3_crud/sql/sql",
|
||||
result, "sql/sql.sql");
|
||||
// 断言 vue 语句
|
||||
assertPathContentEquals("vue3_crud/vue/index",
|
||||
result, "yudao-ui-admin-vue3/src/views/system/user/index.vue");
|
||||
assertPathContentEquals("vue3_crud/vue/form",
|
||||
result, "yudao-ui-admin-vue3/src/views/system/user/UserForm.vue");
|
||||
assertPathContentEquals("vue3_crud/vue/api",
|
||||
result, "yudao-ui-admin-vue3/src/api/system/user/index.ts");
|
||||
assertResult(result, "codegen/vue3_tree");
|
||||
// writeResult(result, "/root/ruoyi-vue-pro/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree");
|
||||
// writeFile(result, "/Users/yunai/test/demo66.zip");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute_vue3_masterNormal() {
|
||||
// 准备请求参数
|
||||
// 主表
|
||||
CodegenTableDO table = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene()).setParentMenuId(888L)
|
||||
.setTableName("infra_demo11_student").setTableComment("学生表")
|
||||
.setModuleName("infra").setBusinessName("demo11").setClassName("InfraDemo11Student")
|
||||
.setClassComment("学生").setAuthor("芋道源码")
|
||||
.setTemplateType(CodegenTemplateTypeEnum.MASTER_NORMAL.getType())
|
||||
.setFrontType(CodegenFrontTypeEnum.VUE3.getType());
|
||||
CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
|
||||
.setId(100L)
|
||||
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
|
||||
.setJavaType("Long").setJavaField("id").setExample("1024")
|
||||
.setCreateOperation(false).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true);
|
||||
CodegenColumnDO nameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("名字").setNullable(false)
|
||||
.setJavaType("String").setJavaField("name").setExample("芋头")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
|
||||
CodegenColumnDO descriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("简介").setNullable(false)
|
||||
.setJavaType("String").setJavaField("description").setExample("我是介绍")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
|
||||
CodegenColumnDO birthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("出生日期").setNullable(false)
|
||||
.setJavaType("LocalDateTime").setJavaField("birthday")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
CodegenColumnDO sexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
|
||||
.setColumnComment("性别").setNullable(false)
|
||||
.setJavaType("Integer").setJavaField("sex").setExample("1")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
|
||||
.setDictType("system_user_sex");
|
||||
CodegenColumnDO enabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
|
||||
.setColumnComment("是否有效").setNullable(false)
|
||||
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
|
||||
.setDictType("infra_boolean_string");
|
||||
CodegenColumnDO avatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("头像").setNullable(false)
|
||||
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
|
||||
CodegenColumnDO videoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("附件").setNullable(true)
|
||||
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
|
||||
CodegenColumnDO memoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("备注").setNullable(false)
|
||||
.setJavaType("String").setJavaField("memo").setExample("我是备注")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
|
||||
CodegenColumnDO createTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("创建时间").setNullable(true)
|
||||
.setJavaType("LocalDateTime").setJavaField("createTime")
|
||||
.setCreateOperation(false).setUpdateOperation(false)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
List<CodegenColumnDO> columns = Arrays.asList(idColumn, nameColumn, descriptionColumn, birthdayColumn,
|
||||
sexColumn, enabledColumn, avatarColumn, videoColumn, memoColumn, createTimeColumn);
|
||||
public void testExecute_vue3_master_normal() {
|
||||
testExecute_vue3_master(CodegenTemplateTypeEnum.MASTER_NORMAL, "codegen/vue3_master_normal");
|
||||
}
|
||||
|
||||
// 子表(联系人)
|
||||
CodegenTableDO contactTable = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene())
|
||||
.setTableName("infra_demo11_student_contact").setTableComment("学生联系人表")
|
||||
.setModuleName("infra").setBusinessName("demo11").setClassName("InfraDemo11StudentContact")
|
||||
.setClassComment("学生联系人").setAuthor("芋道源码")
|
||||
@Test
|
||||
public void testExecute_vue3_master_erp() {
|
||||
testExecute_vue3_master(CodegenTemplateTypeEnum.MASTER_ERP, "codegen/vue3_master_erp");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute_vue3_master_inner() {
|
||||
testExecute_vue3_master(CodegenTemplateTypeEnum.MASTER_INNER, "codegen/vue3_master_inner");
|
||||
}
|
||||
|
||||
private void testExecute_vue3_master(CodegenTemplateTypeEnum templateType,
|
||||
String path) {
|
||||
// 准备参数
|
||||
CodegenTableDO table = getTable("student")
|
||||
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
|
||||
.setTemplateType(templateType.getType());
|
||||
List<CodegenColumnDO> columns = getColumnList("student");
|
||||
// 准备参数(子表)
|
||||
CodegenTableDO contactTable = getTable("contact")
|
||||
.setTemplateType(CodegenTemplateTypeEnum.SUB.getType())
|
||||
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
|
||||
.setSubJoinColumnId(100L).setSubJoinMany(true);
|
||||
CodegenColumnDO contactIdColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
|
||||
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
|
||||
.setJavaType("Long").setJavaField("id").setExample("1024")
|
||||
.setCreateOperation(false).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true);
|
||||
CodegenColumnDO contactStudentIdColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name())
|
||||
.setColumnComment("学生编号").setNullable(false).setPrimaryKey(false)
|
||||
.setJavaType("Long").setJavaField("studentId").setExample("2048")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setId(100L);
|
||||
CodegenColumnDO contactNameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("名字").setNullable(false)
|
||||
.setJavaType("String").setJavaField("name").setExample("芋头")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
|
||||
CodegenColumnDO contactDescriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("简介").setNullable(false)
|
||||
.setJavaType("String").setJavaField("description").setExample("我是介绍")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
|
||||
CodegenColumnDO contactBirthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("出生日期").setNullable(false)
|
||||
.setJavaType("LocalDateTime").setJavaField("birthday")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
CodegenColumnDO contactSexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
|
||||
.setColumnComment("性别").setNullable(false)
|
||||
.setJavaType("Integer").setJavaField("sex").setExample("1")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
|
||||
.setDictType("system_user_sex");
|
||||
CodegenColumnDO contactEnabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
|
||||
.setColumnComment("是否有效").setNullable(false)
|
||||
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
|
||||
.setDictType("infra_boolean_string");
|
||||
CodegenColumnDO contactAvatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("头像").setNullable(false)
|
||||
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
|
||||
CodegenColumnDO contactVideoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("附件").setNullable(true)
|
||||
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
|
||||
CodegenColumnDO contactMemoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("备注").setNullable(false)
|
||||
.setJavaType("String").setJavaField("memo").setExample("我是备注")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
|
||||
CodegenColumnDO contactCreateTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("创建时间").setNullable(true)
|
||||
.setJavaType("LocalDateTime").setJavaField("createTime")
|
||||
.setCreateOperation(false).setUpdateOperation(false)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
List<CodegenColumnDO> contactColumns = Arrays.asList(contactIdColumn, contactStudentIdColumn,
|
||||
contactNameColumn, contactDescriptionColumn, contactBirthdayColumn,
|
||||
contactSexColumn, contactEnabledColumn, contactAvatarColumn, contactVideoColumn, contactMemoColumn, contactCreateTimeColumn);
|
||||
|
||||
// 子表(班主任)
|
||||
CodegenTableDO teacherTable = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene())
|
||||
.setTableName("infra_demo11_student_teacher").setTableComment("学生班主任表")
|
||||
.setModuleName("infra").setBusinessName("demo11").setClassName("InfraDemo11StudentTeacher")
|
||||
.setClassComment("学生班主任").setAuthor("芋道源码")
|
||||
List<CodegenColumnDO> contactColumns = getColumnList("contact");
|
||||
// 准备参数(班主任)
|
||||
CodegenTableDO teacherTable = getTable("teacher")
|
||||
.setTemplateType(CodegenTemplateTypeEnum.SUB.getType())
|
||||
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
|
||||
.setSubJoinColumnId(200L).setSubJoinMany(false);
|
||||
CodegenColumnDO teacherIdColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
|
||||
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
|
||||
.setJavaType("Long").setJavaField("id").setExample("1024")
|
||||
.setCreateOperation(false).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true);
|
||||
CodegenColumnDO teacherStudentIdColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name())
|
||||
.setColumnComment("学生编号").setNullable(false).setPrimaryKey(false)
|
||||
.setJavaType("Long").setJavaField("studentId").setExample("2048")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setId(200L);
|
||||
CodegenColumnDO teacherNameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("名字").setNullable(false)
|
||||
.setJavaType("String").setJavaField("name").setExample("芋头")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
|
||||
CodegenColumnDO teacherDescriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("简介").setNullable(false)
|
||||
.setJavaType("String").setJavaField("description").setExample("我是介绍")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
|
||||
CodegenColumnDO teacherBirthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("出生日期").setNullable(false)
|
||||
.setJavaType("LocalDateTime").setJavaField("birthday")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
CodegenColumnDO teacherSexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
|
||||
.setColumnComment("性别").setNullable(false)
|
||||
.setJavaType("Integer").setJavaField("sex").setExample("1")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
|
||||
.setDictType("system_user_sex");
|
||||
CodegenColumnDO teacherEnabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
|
||||
.setColumnComment("是否有效").setNullable(false)
|
||||
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
|
||||
.setDictType("infra_boolean_string");
|
||||
CodegenColumnDO teacherAvatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("头像").setNullable(false)
|
||||
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
|
||||
CodegenColumnDO teacherVideoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("附件").setNullable(true)
|
||||
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
|
||||
CodegenColumnDO teacherMemoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("备注").setNullable(false)
|
||||
.setJavaType("String").setJavaField("memo").setExample("我是备注")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
|
||||
CodegenColumnDO teacherCreateTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("创建时间").setNullable(true)
|
||||
.setJavaType("LocalDateTime").setJavaField("createTime")
|
||||
.setCreateOperation(false).setUpdateOperation(false)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
List<CodegenColumnDO> teacherColumns = Arrays.asList(teacherIdColumn, teacherStudentIdColumn,
|
||||
teacherNameColumn, teacherDescriptionColumn, teacherBirthdayColumn,
|
||||
teacherSexColumn, teacherEnabledColumn, teacherAvatarColumn, teacherVideoColumn, teacherMemoColumn, teacherCreateTimeColumn);
|
||||
List<CodegenColumnDO> teacherColumns = getColumnList("teacher");
|
||||
|
||||
// 调用
|
||||
Map<String, String> result = codegenEngine.execute(table, columns,
|
||||
Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns));
|
||||
|
||||
// 构建 zip 包
|
||||
writeFile(result, "/Users/yunai/test/demo11.zip");
|
||||
|
||||
// 断言
|
||||
assertEquals(27, result.size());
|
||||
|
||||
for (Map.Entry<String, String> entry : result.entrySet()) {
|
||||
System.out.println(entry.getKey());
|
||||
System.out.println(entry.getValue());
|
||||
System.out.println("");
|
||||
System.out.println("");
|
||||
System.out.println("");
|
||||
}
|
||||
assertResult(result, path);
|
||||
// writeResult(result, "/root/ruoyi-vue-pro/yudao-module-infra/yudao-module-infra-biz/src/test/resources/" + path);
|
||||
// writeFile(result, "/Users/yunai/test/demo11.zip");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute_vue3_masterInner() {
|
||||
// 准备请求参数
|
||||
// 主表
|
||||
CodegenTableDO table = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene()).setParentMenuId(888L)
|
||||
.setTableName("infra_demo12_student").setTableComment("学生表")
|
||||
.setModuleName("infra").setBusinessName("demo12").setClassName("InfraDemo12Student")
|
||||
.setClassComment("学生").setAuthor("芋道源码")
|
||||
// .setTemplateType(CodegenTemplateTypeEnum.MASTER_INNER.getType())
|
||||
.setTemplateType(CodegenTemplateTypeEnum.MASTER_ERP.getType())
|
||||
.setFrontType(CodegenFrontTypeEnum.VUE3.getType());
|
||||
CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
|
||||
.setId(100L)
|
||||
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
|
||||
.setJavaType("Long").setJavaField("id").setExample("1024")
|
||||
.setCreateOperation(false).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true);
|
||||
CodegenColumnDO nameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("名字").setNullable(false)
|
||||
.setJavaType("String").setJavaField("name").setExample("芋头")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
|
||||
CodegenColumnDO descriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("简介").setNullable(false)
|
||||
.setJavaType("String").setJavaField("description").setExample("我是介绍")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
|
||||
CodegenColumnDO birthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("出生日期").setNullable(false)
|
||||
.setJavaType("LocalDateTime").setJavaField("birthday")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
CodegenColumnDO sexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
|
||||
.setColumnComment("性别").setNullable(false)
|
||||
.setJavaType("Integer").setJavaField("sex").setExample("1")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
|
||||
.setDictType("system_user_sex");
|
||||
CodegenColumnDO enabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
|
||||
.setColumnComment("是否有效").setNullable(false)
|
||||
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
|
||||
.setDictType("infra_boolean_string");
|
||||
CodegenColumnDO avatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("头像").setNullable(false)
|
||||
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
|
||||
CodegenColumnDO videoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("附件").setNullable(true)
|
||||
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
|
||||
CodegenColumnDO memoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("备注").setNullable(false)
|
||||
.setJavaType("String").setJavaField("memo").setExample("我是备注")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
|
||||
CodegenColumnDO createTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("创建时间").setNullable(true)
|
||||
.setJavaType("LocalDateTime").setJavaField("createTime")
|
||||
.setCreateOperation(false).setUpdateOperation(false)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
List<CodegenColumnDO> columns = Arrays.asList(idColumn, nameColumn, descriptionColumn, birthdayColumn,
|
||||
sexColumn, enabledColumn, avatarColumn, videoColumn, memoColumn, createTimeColumn);
|
||||
|
||||
// 子表(联系人)
|
||||
CodegenTableDO contactTable = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene())
|
||||
.setTableName("infra_demo12_student_contact").setTableComment("学生联系人表")
|
||||
.setModuleName("infra").setBusinessName("demo12").setClassName("InfraDemo12StudentContact")
|
||||
.setClassComment("学生联系人").setAuthor("芋道源码")
|
||||
.setTemplateType(CodegenTemplateTypeEnum.SUB.getType())
|
||||
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
|
||||
.setSubJoinColumnId(100L).setSubJoinMany(true);
|
||||
CodegenColumnDO contactIdColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
|
||||
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
|
||||
.setJavaType("Long").setJavaField("id").setExample("1024")
|
||||
.setCreateOperation(false).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true);
|
||||
CodegenColumnDO contactStudentIdColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name())
|
||||
.setColumnComment("学生编号").setNullable(false).setPrimaryKey(false)
|
||||
.setJavaType("Long").setJavaField("studentId").setExample("2048")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setId(100L);
|
||||
CodegenColumnDO contactNameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("名字").setNullable(false)
|
||||
.setJavaType("String").setJavaField("name").setExample("芋头")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
|
||||
CodegenColumnDO contactDescriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("简介").setNullable(false)
|
||||
.setJavaType("String").setJavaField("description").setExample("我是介绍")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
|
||||
CodegenColumnDO contactBirthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("出生日期").setNullable(false)
|
||||
.setJavaType("LocalDateTime").setJavaField("birthday")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
CodegenColumnDO contactSexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
|
||||
.setColumnComment("性别").setNullable(false)
|
||||
.setJavaType("Integer").setJavaField("sex").setExample("1")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
|
||||
.setDictType("system_user_sex");
|
||||
CodegenColumnDO contactEnabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
|
||||
.setColumnComment("是否有效").setNullable(false)
|
||||
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
|
||||
.setDictType("infra_boolean_string");
|
||||
CodegenColumnDO contactAvatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("头像").setNullable(false)
|
||||
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
|
||||
CodegenColumnDO contactVideoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("附件").setNullable(true)
|
||||
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
|
||||
CodegenColumnDO contactMemoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("备注").setNullable(false)
|
||||
.setJavaType("String").setJavaField("memo").setExample("我是备注")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
|
||||
CodegenColumnDO contactCreateTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("创建时间").setNullable(true)
|
||||
.setJavaType("LocalDateTime").setJavaField("createTime")
|
||||
.setCreateOperation(false).setUpdateOperation(false)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
List<CodegenColumnDO> contactColumns = Arrays.asList(contactIdColumn, contactStudentIdColumn,
|
||||
contactNameColumn, contactDescriptionColumn, contactBirthdayColumn,
|
||||
contactSexColumn, contactEnabledColumn, contactAvatarColumn, contactVideoColumn, contactMemoColumn, contactCreateTimeColumn);
|
||||
|
||||
// 子表(班主任)
|
||||
CodegenTableDO teacherTable = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene())
|
||||
.setTableName("infra_demo12_student_teacher").setTableComment("学生班主任表")
|
||||
.setModuleName("infra").setBusinessName("demo12").setClassName("InfraDemo12StudentTeacher")
|
||||
.setClassComment("学生班主任").setAuthor("芋道源码")
|
||||
.setTemplateType(CodegenTemplateTypeEnum.SUB.getType())
|
||||
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
|
||||
.setSubJoinColumnId(200L).setSubJoinMany(false);
|
||||
CodegenColumnDO teacherIdColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
|
||||
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
|
||||
.setJavaType("Long").setJavaField("id").setExample("1024")
|
||||
.setCreateOperation(false).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true);
|
||||
CodegenColumnDO teacherStudentIdColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name())
|
||||
.setColumnComment("学生编号").setNullable(false).setPrimaryKey(false)
|
||||
.setJavaType("Long").setJavaField("studentId").setExample("2048")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setId(200L);
|
||||
CodegenColumnDO teacherNameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("名字").setNullable(false)
|
||||
.setJavaType("String").setJavaField("name").setExample("芋头")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
|
||||
CodegenColumnDO teacherDescriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("简介").setNullable(false)
|
||||
.setJavaType("String").setJavaField("description").setExample("我是介绍")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
|
||||
CodegenColumnDO teacherBirthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("出生日期").setNullable(false)
|
||||
.setJavaType("LocalDateTime").setJavaField("birthday")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
CodegenColumnDO teacherSexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
|
||||
.setColumnComment("性别").setNullable(false)
|
||||
.setJavaType("Integer").setJavaField("sex").setExample("1")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
|
||||
.setDictType("system_user_sex");
|
||||
CodegenColumnDO teacherEnabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
|
||||
.setColumnComment("是否有效").setNullable(false)
|
||||
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
|
||||
.setDictType("infra_boolean_string");
|
||||
CodegenColumnDO teacherAvatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("头像").setNullable(false)
|
||||
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
|
||||
CodegenColumnDO teacherVideoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("附件").setNullable(true)
|
||||
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
|
||||
CodegenColumnDO teacherMemoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
|
||||
.setColumnComment("备注").setNullable(false)
|
||||
.setJavaType("String").setJavaField("memo").setExample("我是备注")
|
||||
.setCreateOperation(true).setUpdateOperation(true)
|
||||
.setListOperation(false)
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
|
||||
CodegenColumnDO teacherCreateTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
|
||||
.setColumnComment("创建时间").setNullable(true)
|
||||
.setJavaType("LocalDateTime").setJavaField("createTime")
|
||||
.setCreateOperation(false).setUpdateOperation(false)
|
||||
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
|
||||
.setListOperationResult(true)
|
||||
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
|
||||
List<CodegenColumnDO> teacherColumns = Arrays.asList(teacherIdColumn, teacherStudentIdColumn,
|
||||
teacherNameColumn, teacherDescriptionColumn, teacherBirthdayColumn,
|
||||
teacherSexColumn, teacherEnabledColumn, teacherAvatarColumn, teacherVideoColumn, teacherMemoColumn, teacherCreateTimeColumn);
|
||||
|
||||
// 调用
|
||||
Map<String, String> result = codegenEngine.execute(table, columns,
|
||||
Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns));
|
||||
|
||||
// 构建 zip 包
|
||||
writeFile(result, "/Users/yunai/test/demo12.zip");
|
||||
|
||||
// 断言
|
||||
assertEquals(27, result.size());
|
||||
|
||||
for (Map.Entry<String, String> entry : result.entrySet()) {
|
||||
System.out.println(entry.getKey());
|
||||
System.out.println(entry.getValue());
|
||||
System.out.println("");
|
||||
System.out.println("");
|
||||
System.out.println("");
|
||||
}
|
||||
private static CodegenTableDO getTable(String name) {
|
||||
String content = ResourceUtil.readUtf8Str("codegen/table/" + name + ".json");
|
||||
return JsonUtils.parseObject(content, "table", CodegenTableDO.class);
|
||||
}
|
||||
|
||||
private void assertPathContentEquals(String path, Map<String, String> result, String key) {
|
||||
String pathContent = ResourceUtil.readUtf8Str("codegen/" + path);
|
||||
String valueContent = result.get(key);
|
||||
assertEquals(pathContent, valueContent);
|
||||
private static List<CodegenColumnDO> getColumnList(String name) {
|
||||
String content = ResourceUtil.readUtf8Str("codegen/table/" + name + ".json");
|
||||
List<CodegenColumnDO> list = JsonUtils.parseArray(content, "columns", CodegenColumnDO.class);
|
||||
list.forEach(column -> {
|
||||
if (column.getNullable() == null) {
|
||||
column.setNullable(false);
|
||||
}
|
||||
if (column.getCreateOperation() == null) {
|
||||
column.setCreateOperation(false);
|
||||
}
|
||||
if (column.getUpdateOperation() == null) {
|
||||
column.setUpdateOperation(false);
|
||||
}
|
||||
if (column.getListOperation() == null) {
|
||||
column.setListOperation(false);
|
||||
}
|
||||
if (column.getListOperationResult() == null) {
|
||||
column.setListOperationResult(false);
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static void assertResult(Map<String, String> result, String path) {
|
||||
String assertContent = ResourceUtil.readUtf8Str(path + "/assert.json");
|
||||
List<HashMap> asserts = JsonUtils.parseArray(assertContent, HashMap.class);
|
||||
assertEquals(asserts.size(), result.size());
|
||||
// 校验每个文件
|
||||
asserts.forEach(assertMap -> {
|
||||
String contentPath = (String) assertMap.get("contentPath");
|
||||
String filePath = (String) assertMap.get("filePath");
|
||||
String content = ResourceUtil.readUtf8Str(path + "/" + contentPath);
|
||||
assertEquals(content, result.get(filePath), filePath + ":不匹配");
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 调试专用 ====================
|
||||
|
||||
/**
|
||||
* 将生成的代码,写入到文件
|
||||
*
|
||||
* 用途:方便本地调试
|
||||
* 【调试使用】将生成的代码,写入到文件
|
||||
*
|
||||
* @param result 生成的代码
|
||||
* @param path 写入文件的路径
|
||||
|
@ -810,4 +179,25 @@ public class CodegenEngineTest extends BaseMockitoUnitTest {
|
|||
FileUtil.writeBytes(outputStream.toByteArray(), path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 【调试使用】将生成的结果,写入到文件
|
||||
*
|
||||
* @param result 生成的代码
|
||||
* @param basePath 写入文件的路径(绝对路径)
|
||||
*/
|
||||
private void writeResult(Map<String, String> result, String basePath) {
|
||||
// 写入文件内容
|
||||
List<Map<String, String>> asserts = new ArrayList<>();
|
||||
result.forEach((filePath, fileContent) -> {
|
||||
String lastFilePath = StrUtil.subAfter(filePath, '/', true);
|
||||
String contentPath = StrUtil.subAfter(lastFilePath, '.', true)
|
||||
+ '/' + StrUtil.subBefore(lastFilePath, '.', true);
|
||||
asserts.add(MapUtil.<String, String>builder().put("filePath", filePath)
|
||||
.put("contentPath", contentPath).build());
|
||||
FileUtil.writeUtf8String(fileContent, basePath + "/" + contentPath);
|
||||
});
|
||||
// 写入 assert.json 文件
|
||||
FileUtil.writeUtf8String(JsonUtils.toJsonPrettyString(asserts), basePath +"/assert.json");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
"table": {
|
||||
"id": 10,
|
||||
"scene" : 1,
|
||||
"parentMenuId" : 888,
|
||||
"tableName" : "infra_category",
|
||||
"tableComment" : "分类表",
|
||||
"moduleName" : "infra",
|
||||
"businessName" : "demo",
|
||||
"className" : "InfraCategory",
|
||||
"classComment" : "分类",
|
||||
"author" : "芋道源码",
|
||||
"treeParentColumnId" : 22,
|
||||
"treeNameColumnId" : 11
|
||||
},
|
||||
"columns": [ {
|
||||
"columnName" : "id",
|
||||
"dataType" : "BIGINT",
|
||||
"columnComment" : "编号",
|
||||
"primaryKey" : true,
|
||||
"autoIncrement" : true,
|
||||
"javaType" : "Long",
|
||||
"javaField" : "id",
|
||||
"example" : "1024",
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true
|
||||
}, {
|
||||
"id" : 11,
|
||||
"columnName" : "name",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "名字",
|
||||
"javaType" : "String",
|
||||
"javaField" : "name",
|
||||
"example" : "芋头",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "LIKE",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "input"
|
||||
}, {
|
||||
"id" : 22,
|
||||
"columnName" : "description",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "父编号",
|
||||
"javaType" : "Long",
|
||||
"javaField" : "parentId",
|
||||
"example" : "2048",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true
|
||||
} ]
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
{
|
||||
"table": {
|
||||
"scene" : 1,
|
||||
"tableName" : "infra_student_contact",
|
||||
"tableComment" : "学生联系人表",
|
||||
"moduleName" : "infra",
|
||||
"businessName" : "demo",
|
||||
"className" : "InfraStudentContact",
|
||||
"classComment" : "学生联系人",
|
||||
"author" : "芋道源码"
|
||||
},
|
||||
"columns": [ {
|
||||
"columnName" : "id",
|
||||
"dataType" : "BIGINT",
|
||||
"columnComment" : "编号",
|
||||
"primaryKey" : true,
|
||||
"autoIncrement" : true,
|
||||
"javaType" : "Long",
|
||||
"javaField" : "id",
|
||||
"example" : "1024",
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true
|
||||
}, {
|
||||
"id" : 100,
|
||||
"columnName" : "student_id",
|
||||
"dataType" : "BIGINT",
|
||||
"columnComment" : "学生编号",
|
||||
"javaType" : "Long",
|
||||
"javaField" : "studentId",
|
||||
"example" : "2048",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true
|
||||
}, {
|
||||
"columnName" : "name",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "名字",
|
||||
"javaType" : "String",
|
||||
"javaField" : "name",
|
||||
"example" : "芋头",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "LIKE",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "input"
|
||||
}, {
|
||||
"columnName" : "description",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "简介",
|
||||
"javaType" : "String",
|
||||
"javaField" : "description",
|
||||
"example" : "我是介绍",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "textarea"
|
||||
}, {
|
||||
"columnName" : "birthday",
|
||||
"dataType" : "DATE",
|
||||
"columnComment" : "出生日期",
|
||||
"javaType" : "LocalDateTime",
|
||||
"javaField" : "birthday",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "=",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "datetime"
|
||||
}, {
|
||||
"columnName" : "sex",
|
||||
"dataType" : "INTEGER",
|
||||
"columnComment" : "性别",
|
||||
"javaType" : "Integer",
|
||||
"javaField" : "sex",
|
||||
"dictType" : "system_user_sex",
|
||||
"example" : "1",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "=",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "select"
|
||||
}, {
|
||||
"columnName" : "enabled",
|
||||
"dataType" : "BOOLEAN",
|
||||
"columnComment" : "是否有效",
|
||||
"javaType" : "Boolean",
|
||||
"javaField" : "enabled",
|
||||
"dictType" : "infra_boolean_string",
|
||||
"example" : "true",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "=",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "radio"
|
||||
}, {
|
||||
"columnName" : "avatar",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "头像",
|
||||
"javaType" : "String",
|
||||
"javaField" : "avatar",
|
||||
"example" : "https://www.iocoder.cn/1.png",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "imageUpload"
|
||||
}, {
|
||||
"columnName" : "video",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "附件",
|
||||
"nullable" : true,
|
||||
"javaType" : "String",
|
||||
"javaField" : "video",
|
||||
"example" : "https://www.iocoder.cn/1.mp4",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "fileUpload"
|
||||
}, {
|
||||
"columnName" : "memo",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "备注",
|
||||
"javaType" : "String",
|
||||
"javaField" : "memo",
|
||||
"example" : "我是备注",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "editor"
|
||||
}, {
|
||||
"columnName" : "create_time",
|
||||
"dataType" : "DATE",
|
||||
"columnComment" : "创建时间",
|
||||
"nullable" : true,
|
||||
"javaType" : "LocalDateTime",
|
||||
"javaField" : "createTime",
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "BETWEEN",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "datetime"
|
||||
} ]
|
||||
}
|
|
@ -1,8 +1,135 @@
|
|||
{
|
||||
"table": {
|
||||
|
||||
"id": 1,
|
||||
"scene" : 1,
|
||||
"parentMenuId" : 888,
|
||||
"tableName" : "infra_student",
|
||||
"tableComment" : "学生表",
|
||||
"moduleName" : "infra",
|
||||
"businessName" : "demo",
|
||||
"className" : "InfraStudent",
|
||||
"classComment" : "学生",
|
||||
"author" : "芋道源码"
|
||||
},
|
||||
"columns": [{
|
||||
|
||||
}]
|
||||
"columns": [ {
|
||||
"id" : 100,
|
||||
"columnName" : "id",
|
||||
"dataType" : "BIGINT",
|
||||
"columnComment" : "编号",
|
||||
"primaryKey" : true,
|
||||
"autoIncrement" : true,
|
||||
"javaType" : "Long",
|
||||
"javaField" : "id",
|
||||
"example" : "1024",
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true
|
||||
}, {
|
||||
"columnName" : "name",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "名字",
|
||||
"javaType" : "String",
|
||||
"javaField" : "name",
|
||||
"example" : "芋头",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "LIKE",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "input"
|
||||
}, {
|
||||
"columnName" : "description",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "简介",
|
||||
"javaType" : "String",
|
||||
"javaField" : "description",
|
||||
"example" : "我是介绍",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "textarea"
|
||||
}, {
|
||||
"columnName" : "birthday",
|
||||
"dataType" : "DATE",
|
||||
"columnComment" : "出生日期",
|
||||
"javaType" : "LocalDateTime",
|
||||
"javaField" : "birthday",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "=",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "datetime"
|
||||
}, {
|
||||
"columnName" : "sex",
|
||||
"dataType" : "INTEGER",
|
||||
"columnComment" : "性别",
|
||||
"javaType" : "Integer",
|
||||
"javaField" : "sex",
|
||||
"dictType" : "system_user_sex",
|
||||
"example" : "1",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "=",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "select"
|
||||
}, {
|
||||
"columnName" : "enabled",
|
||||
"dataType" : "BOOLEAN",
|
||||
"columnComment" : "是否有效",
|
||||
"javaType" : "Boolean",
|
||||
"javaField" : "enabled",
|
||||
"dictType" : "infra_boolean_string",
|
||||
"example" : "true",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "=",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "radio"
|
||||
}, {
|
||||
"columnName" : "avatar",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "头像",
|
||||
"javaType" : "String",
|
||||
"javaField" : "avatar",
|
||||
"example" : "https://www.iocoder.cn/1.png",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "imageUpload"
|
||||
}, {
|
||||
"columnName" : "video",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "附件",
|
||||
"javaType" : "String",
|
||||
"javaField" : "video",
|
||||
"example" : "https://www.iocoder.cn/1.mp4",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "fileUpload"
|
||||
}, {
|
||||
"columnName" : "memo",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "备注",
|
||||
"javaType" : "String",
|
||||
"javaField" : "memo",
|
||||
"example" : "我是备注",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "editor"
|
||||
}, {
|
||||
"columnName" : "create_time",
|
||||
"dataType" : "DATE",
|
||||
"columnComment" : "创建时间",
|
||||
"nullable" : true,
|
||||
"javaType" : "LocalDateTime",
|
||||
"javaField" : "createTime",
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "BETWEEN",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "datetime"
|
||||
} ]
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
{
|
||||
"table": {
|
||||
"scene" : 1,
|
||||
"tableName" : "infra_student_teacher",
|
||||
"tableComment" : "学生班主任表",
|
||||
"moduleName" : "infra",
|
||||
"businessName" : "demo",
|
||||
"className" : "InfraStudentTeacher",
|
||||
"classComment" : "学生班主任",
|
||||
"author" : "芋道源码"
|
||||
},
|
||||
"columns": [ {
|
||||
"columnName" : "id",
|
||||
"dataType" : "BIGINT",
|
||||
"columnComment" : "编号",
|
||||
"primaryKey" : true,
|
||||
"autoIncrement" : true,
|
||||
"javaType" : "Long",
|
||||
"javaField" : "id",
|
||||
"example" : "1024",
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true
|
||||
}, {
|
||||
"id" : 200,
|
||||
"columnName" : "student_id",
|
||||
"dataType" : "BIGINT",
|
||||
"columnComment" : "学生编号",
|
||||
"javaType" : "Long",
|
||||
"javaField" : "studentId",
|
||||
"example" : "2048",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true
|
||||
}, {
|
||||
"columnName" : "name",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "名字",
|
||||
"javaType" : "String",
|
||||
"javaField" : "name",
|
||||
"example" : "芋头",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "LIKE",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "input"
|
||||
}, {
|
||||
"columnName" : "description",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "简介",
|
||||
"javaType" : "String",
|
||||
"javaField" : "description",
|
||||
"example" : "我是介绍",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "textarea"
|
||||
}, {
|
||||
"columnName" : "birthday",
|
||||
"dataType" : "DATE",
|
||||
"columnComment" : "出生日期",
|
||||
"javaType" : "LocalDateTime",
|
||||
"javaField" : "birthday",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "=",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "datetime"
|
||||
}, {
|
||||
"columnName" : "sex",
|
||||
"dataType" : "INTEGER",
|
||||
"columnComment" : "性别",
|
||||
"javaType" : "Integer",
|
||||
"javaField" : "sex",
|
||||
"dictType" : "system_user_sex",
|
||||
"example" : "1",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "=",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "select"
|
||||
}, {
|
||||
"columnName" : "enabled",
|
||||
"dataType" : "BOOLEAN",
|
||||
"columnComment" : "是否有效",
|
||||
"javaType" : "Boolean",
|
||||
"javaField" : "enabled",
|
||||
"dictType" : "infra_boolean_string",
|
||||
"example" : "true",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "=",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "radio"
|
||||
}, {
|
||||
"columnName" : "avatar",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "头像",
|
||||
"javaType" : "String",
|
||||
"javaField" : "avatar",
|
||||
"example" : "https://www.iocoder.cn/1.png",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "imageUpload"
|
||||
}, {
|
||||
"columnName" : "video",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "附件",
|
||||
"nullable" : true,
|
||||
"javaType" : "String",
|
||||
"javaField" : "video",
|
||||
"example" : "https://www.iocoder.cn/1.mp4",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "fileUpload"
|
||||
}, {
|
||||
"columnName" : "memo",
|
||||
"dataType" : "VARCHAR",
|
||||
"columnComment" : "备注",
|
||||
"javaType" : "String",
|
||||
"javaField" : "memo",
|
||||
"example" : "我是备注",
|
||||
"createOperation" : true,
|
||||
"updateOperation" : true,
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "editor"
|
||||
}, {
|
||||
"columnName" : "create_time",
|
||||
"dataType" : "DATE",
|
||||
"columnComment" : "创建时间",
|
||||
"nullable" : true,
|
||||
"javaType" : "LocalDateTime",
|
||||
"javaField" : "createTime",
|
||||
"listOperation" : true,
|
||||
"listOperationCondition" : "BETWEEN",
|
||||
"listOperationResult" : true,
|
||||
"htmlType" : "datetime"
|
||||
} ]
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
// TODO 待办:请将下面的错误码复制到 yudao-module-system-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!!
|
||||
// ========== 用户 TODO 补充编号 ==========
|
||||
ErrorCode USER_NOT_EXISTS = new ErrorCode(TODO 补充编号, "用户不存在");
|
|
@ -1,53 +0,0 @@
|
|||
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import javax.validation.constraints.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
/**
|
||||
* 用户 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||
*/
|
||||
@Data
|
||||
public class SystemUserBaseVO {
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
|
||||
@NotEmpty(message = "名字不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "头像", example = "https://www.iocoder.cn/1.png")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "视频", example = "https://www.iocoder.cn/1.mp4")
|
||||
private String video;
|
||||
|
||||
@Schema(description = "个人简介", example = "我是介绍")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "性别 1", example = "男")
|
||||
private String sex1;
|
||||
|
||||
@Schema(description = "性别 2", example = "1")
|
||||
private Integer sex2;
|
||||
|
||||
@Schema(description = "性别 3", example = "true")
|
||||
private Boolean sex3;
|
||||
|
||||
@Schema(description = "出生日期")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "备注", example = "我是备注")
|
||||
private String memo;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
package cn.iocoder.yudao.module.system.controller.admin.user;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
import javax.validation.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;
|
||||
import cn.iocoder.yudao.module.system.convert.user.SystemUserConvert;
|
||||
import cn.iocoder.yudao.module.system.service.user.SystemUserService;
|
||||
|
||||
@Tag(name = "管理后台 - 用户")
|
||||
@RestController
|
||||
@RequestMapping("/system/user")
|
||||
@Validated
|
||||
public class SystemUserController {
|
||||
|
||||
@Resource
|
||||
private SystemUserService userService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建用户")
|
||||
@PreAuthorize("@ss.hasPermission('system:user:create')")
|
||||
public CommonResult<Long> createUser(@Valid @RequestBody SystemUserCreateReqVO createReqVO) {
|
||||
return success(userService.createUser(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新用户")
|
||||
@PreAuthorize("@ss.hasPermission('system:user:update')")
|
||||
public CommonResult<Boolean> updateUser(@Valid @RequestBody SystemUserUpdateReqVO updateReqVO) {
|
||||
userService.updateUser(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除用户")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('system:user:delete')")
|
||||
public CommonResult<Boolean> deleteUser(@RequestParam("id") Long id) {
|
||||
userService.deleteUser(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得用户")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('system:user:query')")
|
||||
public CommonResult<SystemUserRespVO> getUser(@RequestParam("id") Long id) {
|
||||
SystemUserDO user = userService.getUser(id);
|
||||
return success(SystemUserConvert.INSTANCE.convert(user));
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获得用户列表")
|
||||
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
|
||||
@PreAuthorize("@ss.hasPermission('system:user:query')")
|
||||
public CommonResult<List<SystemUserRespVO>> getUserList(@RequestParam("ids") Collection<Long> ids) {
|
||||
List<SystemUserDO> list = userService.getUserList(ids);
|
||||
return success(SystemUserConvert.INSTANCE.convertList(list));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得用户分页")
|
||||
@PreAuthorize("@ss.hasPermission('system:user:query')")
|
||||
public CommonResult<PageResult<SystemUserRespVO>> getUserPage(@Valid SystemUserPageReqVO pageVO) {
|
||||
PageResult<SystemUserDO> pageResult = userService.getUserPage(pageVO);
|
||||
return success(SystemUserConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出用户 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('system:user:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportUserExcel(@Valid SystemUserExportReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
List<SystemUserDO> list = userService.getUserList(exportReqVO);
|
||||
// 导出 Excel
|
||||
List<SystemUserExcelVO> datas = SystemUserConvert.INSTANCE.convertList02(list);
|
||||
ExcelUtils.write(response, "用户.xls", "数据", SystemUserExcelVO.class, datas);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package cn.iocoder.yudao.module.system.convert.user;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;
|
||||
|
||||
/**
|
||||
* 用户 Convert
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface SystemUserConvert {
|
||||
|
||||
SystemUserConvert INSTANCE = Mappers.getMapper(SystemUserConvert.class);
|
||||
|
||||
SystemUserDO convert(SystemUserCreateReqVO bean);
|
||||
|
||||
SystemUserDO convert(SystemUserUpdateReqVO bean);
|
||||
|
||||
SystemUserRespVO convert(SystemUserDO bean);
|
||||
|
||||
List<SystemUserRespVO> convertList(List<SystemUserDO> list);
|
||||
|
||||
PageResult<SystemUserRespVO> convertPage(PageResult<SystemUserDO> page);
|
||||
|
||||
List<SystemUserExcelVO> convertList02(List<SystemUserDO> list);
|
||||
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
@Schema(description = "管理后台 - 用户创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SystemUserCreateReqVO extends SystemUserBaseVO {
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||
|
||||
|
||||
/**
|
||||
* 用户 Excel VO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class SystemUserExcelVO {
|
||||
|
||||
@ExcelProperty("编号")
|
||||
private Long id;
|
||||
|
||||
@ExcelProperty("名字")
|
||||
private String name;
|
||||
|
||||
@ExcelProperty("头像")
|
||||
private String avatar;
|
||||
|
||||
@ExcelProperty("视频")
|
||||
private String video;
|
||||
|
||||
@ExcelProperty("个人简介")
|
||||
private String description;
|
||||
|
||||
@ExcelProperty(value = "性别 1", converter = DictConvert.class)
|
||||
@DictFormat("system_sex1") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
|
||||
private String sex1;
|
||||
|
||||
@ExcelProperty(value = "性别 2", converter = DictConvert.class)
|
||||
@DictFormat("system_sex2") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
|
||||
private Integer sex2;
|
||||
|
||||
@ExcelProperty(value = "性别 3", converter = DictConvert.class)
|
||||
@DictFormat("system_sex3") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
|
||||
private Boolean sex3;
|
||||
|
||||
@ExcelProperty("出生日期")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@ExcelProperty("备注")
|
||||
private String memo;
|
||||
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package cn.iocoder.yudao.module.system.dal.mysql.user;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;
|
||||
|
||||
/**
|
||||
* 用户 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface SystemUserMapper extends BaseMapperX<SystemUserDO> {
|
||||
|
||||
default PageResult<SystemUserDO> selectPage(SystemUserPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<SystemUserDO>()
|
||||
.likeIfPresent(SystemUserDO::getName, reqVO.getName())
|
||||
.eqIfPresent(SystemUserDO::getSex1, reqVO.getSex1())
|
||||
.eqIfPresent(SystemUserDO::getSex2, reqVO.getSex2())
|
||||
.eqIfPresent(SystemUserDO::getBirthday, reqVO.getBirthday())
|
||||
.betweenIfPresent(SystemUserDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(SystemUserDO::getId));
|
||||
}
|
||||
|
||||
default List<SystemUserDO> selectList(SystemUserExportReqVO reqVO) {
|
||||
return selectList(new LambdaQueryWrapperX<SystemUserDO>()
|
||||
.likeIfPresent(SystemUserDO::getName, reqVO.getName())
|
||||
.eqIfPresent(SystemUserDO::getSex1, reqVO.getSex1())
|
||||
.eqIfPresent(SystemUserDO::getSex2, reqVO.getSex2())
|
||||
.eqIfPresent(SystemUserDO::getBirthday, reqVO.getBirthday())
|
||||
.betweenIfPresent(SystemUserDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(SystemUserDO::getId));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 用户 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SystemUserRespVO extends SystemUserBaseVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
package cn.iocoder.yudao.module.system.service.user;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
/**
|
||||
* 用户 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface SystemUserService {
|
||||
|
||||
/**
|
||||
* 创建用户
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createUser(@Valid SystemUserCreateReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新用户
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateUser(@Valid SystemUserUpdateReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteUser(Long id);
|
||||
|
||||
/**
|
||||
* 获得用户
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 用户
|
||||
*/
|
||||
SystemUserDO getUser(Long id);
|
||||
|
||||
/**
|
||||
* 获得用户列表
|
||||
*
|
||||
* @param ids 编号
|
||||
* @return 用户列表
|
||||
*/
|
||||
List<SystemUserDO> getUserList(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得用户分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 用户分页
|
||||
*/
|
||||
PageResult<SystemUserDO> getUserPage(SystemUserPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得用户列表, 用于 Excel 导出
|
||||
*
|
||||
* @param exportReqVO 查询条件
|
||||
* @return 用户列表
|
||||
*/
|
||||
List<SystemUserDO> getUserList(SystemUserExportReqVO exportReqVO);
|
||||
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
package cn.iocoder.yudao.module.system.service.user;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.*;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import cn.iocoder.yudao.module.system.convert.user.SystemUserConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.user.SystemUserMapper;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
|
||||
/**
|
||||
* 用户 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class SystemUserServiceImpl implements SystemUserService {
|
||||
|
||||
@Resource
|
||||
private SystemUserMapper userMapper;
|
||||
|
||||
@Override
|
||||
public Long createUser(SystemUserCreateReqVO createReqVO) {
|
||||
// 插入
|
||||
SystemUserDO user = SystemUserConvert.INSTANCE.convert(createReqVO);
|
||||
userMapper.insert(user);
|
||||
// 返回
|
||||
return user.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUser(SystemUserUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateUserExists(updateReqVO.getId());
|
||||
// 更新
|
||||
SystemUserDO updateObj = SystemUserConvert.INSTANCE.convert(updateReqVO);
|
||||
userMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteUser(Long id) {
|
||||
// 校验存在
|
||||
validateUserExists(id);
|
||||
// 删除
|
||||
userMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateUserExists(Long id) {
|
||||
if (userMapper.selectById(id) == null) {
|
||||
throw exception(USER_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SystemUserDO getUser(Long id) {
|
||||
return userMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SystemUserDO> getUserList(Collection<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return ListUtil.empty();
|
||||
}
|
||||
return userMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<SystemUserDO> getUserPage(SystemUserPageReqVO pageReqVO) {
|
||||
return userMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SystemUserDO> getUserList(SystemUserExportReqVO exportReqVO) {
|
||||
return userMapper.selectList(exportReqVO);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,191 +0,0 @@
|
|||
package cn.iocoder.yudao.module.system.service.user;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import cn.iocoder.yudao.module.framework.test.core.ut.BaseDbUnitTest;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.user.SystemUserMapper;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.hutool.core.util.RandomUtil.*;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.module.framework.test.core.util.AssertUtils.*;
|
||||
import static cn.iocoder.yudao.module.framework.test.core.util.RandomUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* {@link SystemUserServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Import(SystemUserServiceImpl.class)
|
||||
public class SystemUserServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private SystemUserServiceImpl userService;
|
||||
|
||||
@Resource
|
||||
private SystemUserMapper userMapper;
|
||||
|
||||
@Test
|
||||
public void testCreateUser_success() {
|
||||
// 准备参数
|
||||
SystemUserCreateReqVO reqVO = randomPojo(SystemUserCreateReqVO.class);
|
||||
|
||||
// 调用
|
||||
Long userId = userService.createUser(reqVO);
|
||||
// 断言
|
||||
assertNotNull(userId);
|
||||
// 校验记录的属性是否正确
|
||||
SystemUserDO user = userMapper.selectById(userId);
|
||||
assertPojoEquals(reqVO, user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateUser_success() {
|
||||
// mock 数据
|
||||
SystemUserDO dbUser = randomPojo(SystemUserDO.class);
|
||||
userMapper.insert(dbUser);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
SystemUserUpdateReqVO reqVO = randomPojo(SystemUserUpdateReqVO.class, o -> {
|
||||
o.setId(dbUser.getId()); // 设置更新的 ID
|
||||
});
|
||||
|
||||
// 调用
|
||||
userService.updateUser(reqVO);
|
||||
// 校验是否更新正确
|
||||
SystemUserDO user = userMapper.selectById(reqVO.getId()); // 获取最新的
|
||||
assertPojoEquals(reqVO, user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateUser_notExists() {
|
||||
// 准备参数
|
||||
SystemUserUpdateReqVO reqVO = randomPojo(SystemUserUpdateReqVO.class);
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> userService.updateUser(reqVO), USER_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteUser_success() {
|
||||
// mock 数据
|
||||
SystemUserDO dbUser = randomPojo(SystemUserDO.class);
|
||||
userMapper.insert(dbUser);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
Long id = dbUser.getId();
|
||||
|
||||
// 调用
|
||||
userService.deleteUser(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(userMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteUser_notExists() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> userService.deleteUser(id), USER_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
|
||||
public void testGetUserPage() {
|
||||
// mock 数据
|
||||
SystemUserDO dbUser = randomPojo(SystemUserDO.class, o -> { // 等会查询到
|
||||
o.setName(null);
|
||||
o.setSex1(null);
|
||||
o.setSex2(null);
|
||||
o.setSex3(null);
|
||||
o.setBirthday(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
userMapper.insert(dbUser);
|
||||
// 测试 name 不匹配
|
||||
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setName(null)));
|
||||
// 测试 sex1 不匹配
|
||||
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex1(null)));
|
||||
// 测试 sex2 不匹配
|
||||
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex2(null)));
|
||||
// 测试 sex3 不匹配
|
||||
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex3(null)));
|
||||
// 测试 birthday 不匹配
|
||||
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setBirthday(null)));
|
||||
// 测试 createTime 不匹配
|
||||
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setCreateTime(null)));
|
||||
// 准备参数
|
||||
SystemUserPageReqVO reqVO = new SystemUserPageReqVO();
|
||||
reqVO.setName(null);
|
||||
reqVO.setSex1(null);
|
||||
reqVO.setSex2(null);
|
||||
reqVO.setSex3(null);
|
||||
reqVO.setBirthday(null);
|
||||
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
|
||||
|
||||
// 调用
|
||||
PageResult<SystemUserDO> pageResult = userService.getUserPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbUser, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
|
||||
public void testGetUserList() {
|
||||
// mock 数据
|
||||
SystemUserDO dbUser = randomPojo(SystemUserDO.class, o -> { // 等会查询到
|
||||
o.setName(null);
|
||||
o.setSex1(null);
|
||||
o.setSex2(null);
|
||||
o.setSex3(null);
|
||||
o.setBirthday(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
userMapper.insert(dbUser);
|
||||
// 测试 name 不匹配
|
||||
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setName(null)));
|
||||
// 测试 sex1 不匹配
|
||||
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex1(null)));
|
||||
// 测试 sex2 不匹配
|
||||
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex2(null)));
|
||||
// 测试 sex3 不匹配
|
||||
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex3(null)));
|
||||
// 测试 birthday 不匹配
|
||||
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setBirthday(null)));
|
||||
// 测试 createTime 不匹配
|
||||
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setCreateTime(null)));
|
||||
// 准备参数
|
||||
SystemUserExportReqVO reqVO = new SystemUserExportReqVO();
|
||||
reqVO.setName(null);
|
||||
reqVO.setSex1(null);
|
||||
reqVO.setSex2(null);
|
||||
reqVO.setSex3(null);
|
||||
reqVO.setBirthday(null);
|
||||
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
|
||||
|
||||
// 调用
|
||||
List<SystemUserDO> list = userService.getUserList(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, list.size());
|
||||
assertPojoEquals(dbUser, list.get(0));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
@Schema(description = "管理后台 - 用户更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SystemUserUpdateReqVO extends SystemUserBaseVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Long id;
|
||||
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
-- 将该建表 SQL 语句,添加到 yudao-module-system-biz 模块的 test/resources/sql/create_tables.sql 文件里
|
||||
CREATE TABLE IF NOT EXISTS "system_user" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"name" varchar NOT NULL,
|
||||
"avatar" varchar,
|
||||
"video" varchar,
|
||||
"description" varchar,
|
||||
"sex1" varchar,
|
||||
"sex2" int,
|
||||
"sex3" bit,
|
||||
"birthday" varchar,
|
||||
"memo" varchar,
|
||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '用户表';
|
||||
|
||||
-- 将该删表 SQL 语句,添加到 yudao-module-system-biz 模块的 test/resources/sql/clean.sql 文件里
|
||||
DELETE FROM "system_user";
|
|
@ -1,45 +0,0 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
export interface UserVO {
|
||||
id: number
|
||||
name: string
|
||||
avatar: string
|
||||
video: string
|
||||
description: string
|
||||
sex1: string
|
||||
sex2: number
|
||||
sex3: boolean
|
||||
birthday: Date
|
||||
memo: string
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
// 查询用户列表
|
||||
export const getUserPage = async (params) => {
|
||||
return await request.get({ url: `/system/user/page`, params })
|
||||
}
|
||||
|
||||
// 查询用户详情
|
||||
export const getUser = async (id: number) => {
|
||||
return await request.get({ url: `/system/user/get?id=` + id })
|
||||
}
|
||||
|
||||
// 新增用户
|
||||
export const createUser = async (data: UserVO) => {
|
||||
return await request.post({ url: `/system/user/create`, data })
|
||||
}
|
||||
|
||||
// 修改用户
|
||||
export const updateUser = async (data: UserVO) => {
|
||||
return await request.put({ url: `/system/user/update`, data })
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
export const deleteUser = async (id: number) => {
|
||||
return await request.delete({ url: `/system/user/delete?id=` + id })
|
||||
}
|
||||
|
||||
// 导出用户 Excel
|
||||
export const exportUser = async (params) => {
|
||||
return await request.download({ url: `/system/user/export-excel`, params })
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
[ {
|
||||
"contentPath" : "java/InfraStudentPageReqVO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentRespVO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentSaveReqVO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentController",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentDO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentContactDO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentTeacherDO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentMapper",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentContactMapper",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentTeacherMapper",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java"
|
||||
}, {
|
||||
"contentPath" : "xml/InfraStudentMapper",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentServiceImpl",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentService",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentServiceImplTest",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java"
|
||||
}, {
|
||||
"contentPath" : "java/ErrorCodeConstants_手动操作",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java"
|
||||
}, {
|
||||
"contentPath" : "sql/sql",
|
||||
"filePath" : "sql/sql.sql"
|
||||
}, {
|
||||
"contentPath" : "sql/h2",
|
||||
"filePath" : "sql/h2.sql"
|
||||
}, {
|
||||
"contentPath" : "vue/index",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue"
|
||||
}, {
|
||||
"contentPath" : "vue/StudentForm",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/StudentForm.vue"
|
||||
}, {
|
||||
"contentPath" : "vue/StudentContactForm",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactForm.vue"
|
||||
}, {
|
||||
"contentPath" : "vue/StudentTeacherForm",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherForm.vue"
|
||||
}, {
|
||||
"contentPath" : "vue/StudentContactList",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactList.vue"
|
||||
}, {
|
||||
"contentPath" : "vue/StudentTeacherList",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherList.vue"
|
||||
}, {
|
||||
"contentPath" : "ts/index",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts"
|
||||
} ]
|
|
@ -0,0 +1,6 @@
|
|||
// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!!
|
||||
// ========== 学生 TODO 补充编号 ==========
|
||||
ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在");
|
||||
ErrorCode STUDENT_CONTACT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生联系人不存在");
|
||||
ErrorCode STUDENT_TEACHER_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生班主任不存在");
|
||||
ErrorCode STUDENT_TEACHER_EXISTS = new ErrorCode(TODO 补充编号, "学生班主任已存在");
|
|
@ -1,4 +1,4 @@
|
|||
package cn.iocoder.yudao.module.system.dal.dataobject.user;
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
|
@ -8,63 +8,61 @@ import com.baomidou.mybatisplus.annotation.*;
|
|||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 用户 DO
|
||||
* 学生联系人 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("system_user")
|
||||
@KeySequence("system_user_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@TableName("infra_student_contact")
|
||||
@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SystemUserDO extends BaseDO {
|
||||
public class InfraStudentContactDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 学生编号
|
||||
*/
|
||||
private Long studentId;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 简介
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 出生日期
|
||||
*/
|
||||
private LocalDateTime birthday;
|
||||
/**
|
||||
* 性别
|
||||
*
|
||||
* 枚举 {@link TODO system_user_sex 对应的类}
|
||||
*/
|
||||
private Integer sex;
|
||||
/**
|
||||
* 是否有效
|
||||
*
|
||||
* 枚举 {@link TODO infra_boolean_string 对应的类}
|
||||
*/
|
||||
private Boolean enabled;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
/**
|
||||
* 视频
|
||||
* 附件
|
||||
*/
|
||||
private String video;
|
||||
/**
|
||||
* 个人简介
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 性别 1
|
||||
*
|
||||
* 枚举 {@link TODO system_sex1 对应的类}
|
||||
*/
|
||||
private String sex1;
|
||||
/**
|
||||
* 性别 2
|
||||
*
|
||||
* 枚举 {@link TODO system_sex2 对应的类}
|
||||
*/
|
||||
private Integer sex2;
|
||||
/**
|
||||
* 性别 3
|
||||
*
|
||||
* 枚举 {@link TODO system_sex3 对应的类}
|
||||
*/
|
||||
private Boolean sex3;
|
||||
/**
|
||||
* 出生日期
|
||||
*/
|
||||
private LocalDateTime birthday;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
|
@ -0,0 +1,30 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 学生联系人 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface InfraStudentContactMapper extends BaseMapperX<InfraStudentContactDO> {
|
||||
|
||||
default PageResult<InfraStudentContactDO> selectPage(PageParam reqVO, Long studentId) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentContactDO>()
|
||||
.eq(InfraStudentContactDO::getStudentId, studentId)
|
||||
.orderByDesc(InfraStudentContactDO::getId));
|
||||
}
|
||||
|
||||
default int deleteByStudentId(Long studentId) {
|
||||
return delete(InfraStudentContactDO::getStudentId, studentId);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
package cn.iocoder.yudao.module.infra.controller.admin.demo;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
import javax.validation.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService;
|
||||
|
||||
@Tag(name = "管理后台 - 学生")
|
||||
@RestController
|
||||
@RequestMapping("/infra/student")
|
||||
@Validated
|
||||
public class InfraStudentController {
|
||||
|
||||
@Resource
|
||||
private InfraStudentService studentService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建学生")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:create')")
|
||||
public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) {
|
||||
return success(studentService.createStudent(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新学生")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:update')")
|
||||
public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) {
|
||||
studentService.updateStudent(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除学生")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:delete')")
|
||||
public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) {
|
||||
studentService.deleteStudent(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得学生")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) {
|
||||
InfraStudentDO student = studentService.getStudent(id);
|
||||
return success(BeanUtils.toBean(student, InfraStudentRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得学生分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) {
|
||||
PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出学生 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class,
|
||||
BeanUtils.toBean(list, InfraStudentRespVO.class));
|
||||
}
|
||||
|
||||
// ==================== 子表(学生联系人) ====================
|
||||
|
||||
@GetMapping("/student-contact/page")
|
||||
@Operation(summary = "获得学生联系人分页")
|
||||
@Parameter(name = "studentId", description = "学生编号")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<PageResult<InfraStudentContactDO>> getStudentContactPage(PageParam pageReqVO,
|
||||
@RequestParam("studentId") Long studentId) {
|
||||
return success(studentService.getStudentContactPage(pageReqVO, studentId));
|
||||
}
|
||||
|
||||
@PostMapping("/student-contact/create")
|
||||
@Operation(summary = "创建学生联系人")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:create')")
|
||||
public CommonResult<Long> createStudentContact(@Valid @RequestBody InfraStudentContactDO studentContact) {
|
||||
return success(studentService.createStudentContact(studentContact));
|
||||
}
|
||||
|
||||
@PutMapping("/student-contact/update")
|
||||
@Operation(summary = "更新学生联系人")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:update')")
|
||||
public CommonResult<Boolean> updateStudentContact(@Valid @RequestBody InfraStudentContactDO studentContact) {
|
||||
studentService.updateStudentContact(studentContact);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/student-contact/delete")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@Operation(summary = "删除学生联系人")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:delete')")
|
||||
public CommonResult<Boolean> deleteStudentContact(@RequestParam("id") Long id) {
|
||||
studentService.deleteStudentContact(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/student-contact/get")
|
||||
@Operation(summary = "获得学生联系人")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<InfraStudentContactDO> getStudentContact(@RequestParam("id") Long id) {
|
||||
return success(studentService.getStudentContact(id));
|
||||
}
|
||||
|
||||
// ==================== 子表(学生班主任) ====================
|
||||
|
||||
@GetMapping("/student-teacher/page")
|
||||
@Operation(summary = "获得学生班主任分页")
|
||||
@Parameter(name = "studentId", description = "学生编号")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<PageResult<InfraStudentTeacherDO>> getStudentTeacherPage(PageParam pageReqVO,
|
||||
@RequestParam("studentId") Long studentId) {
|
||||
return success(studentService.getStudentTeacherPage(pageReqVO, studentId));
|
||||
}
|
||||
|
||||
@PostMapping("/student-teacher/create")
|
||||
@Operation(summary = "创建学生班主任")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:create')")
|
||||
public CommonResult<Long> createStudentTeacher(@Valid @RequestBody InfraStudentTeacherDO studentTeacher) {
|
||||
return success(studentService.createStudentTeacher(studentTeacher));
|
||||
}
|
||||
|
||||
@PutMapping("/student-teacher/update")
|
||||
@Operation(summary = "更新学生班主任")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:update')")
|
||||
public CommonResult<Boolean> updateStudentTeacher(@Valid @RequestBody InfraStudentTeacherDO studentTeacher) {
|
||||
studentService.updateStudentTeacher(studentTeacher);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/student-teacher/delete")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@Operation(summary = "删除学生班主任")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:delete')")
|
||||
public CommonResult<Boolean> deleteStudentTeacher(@RequestParam("id") Long id) {
|
||||
studentService.deleteStudentTeacher(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/student-teacher/get")
|
||||
@Operation(summary = "获得学生班主任")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<InfraStudentTeacherDO> getStudentTeacher(@RequestParam("id") Long id) {
|
||||
return success(studentService.getStudentTeacher(id));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 学生 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_student")
|
||||
@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class InfraStudentDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 简介
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 出生日期
|
||||
*/
|
||||
private LocalDateTime birthday;
|
||||
/**
|
||||
* 性别
|
||||
*
|
||||
* 枚举 {@link TODO system_user_sex 对应的类}
|
||||
*/
|
||||
private Integer sex;
|
||||
/**
|
||||
* 是否有效
|
||||
*
|
||||
* 枚举 {@link TODO infra_boolean_string 对应的类}
|
||||
*/
|
||||
private Boolean enabled;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
/**
|
||||
* 附件
|
||||
*/
|
||||
private String video;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
|
||||
/**
|
||||
* 学生 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> {
|
||||
|
||||
default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>()
|
||||
.likeIfPresent(InfraStudentDO::getName, reqVO.getName())
|
||||
.eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday())
|
||||
.eqIfPresent(InfraStudentDO::getSex, reqVO.getSex())
|
||||
.eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled())
|
||||
.betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(InfraStudentDO::getId));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
|
@ -9,27 +9,24 @@ import java.time.LocalDateTime;
|
|||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 用户分页 Request VO")
|
||||
@Schema(description = "管理后台 - 学生分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SystemUserPageReqVO extends PageParam {
|
||||
public class InfraStudentPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "名字", example = "芋头")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "性别 1", example = "男")
|
||||
private String sex1;
|
||||
|
||||
@Schema(description = "性别 2", example = "1")
|
||||
private Integer sex2;
|
||||
|
||||
@Schema(description = "性别 3", example = "true")
|
||||
private Boolean sex3;
|
||||
|
||||
@Schema(description = "出生日期")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "性别", example = "1")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "是否有效", example = "true")
|
||||
private Boolean enabled;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
|
@ -0,0 +1,60 @@
|
|||
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.excel.annotation.*;
|
||||
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||
|
||||
@Schema(description = "管理后台 - 学生 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class InfraStudentRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@ExcelProperty("编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
|
||||
@ExcelProperty("名字")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
|
||||
@ExcelProperty("简介")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("出生日期")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty(value = "性别", converter = DictConvert.class)
|
||||
@DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@ExcelProperty(value = "是否有效", converter = DictConvert.class)
|
||||
@DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Boolean enabled;
|
||||
|
||||
@Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
||||
@ExcelProperty("头像")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
|
||||
@ExcelProperty("附件")
|
||||
private String video;
|
||||
|
||||
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
|
||||
@ExcelProperty("备注")
|
||||
private String memo;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import javax.validation.constraints.*;
|
||||
import java.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
|
||||
@Schema(description = "管理后台 - 学生新增/修改 Request VO")
|
||||
@Data
|
||||
public class InfraStudentSaveReqVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
|
||||
@NotEmpty(message = "名字不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
|
||||
@NotEmpty(message = "简介不能为空")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "出生日期不能为空")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "性别不能为空")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@NotNull(message = "是否有效不能为空")
|
||||
private Boolean enabled;
|
||||
|
||||
@Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
||||
@NotEmpty(message = "头像不能为空")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
|
||||
@NotEmpty(message = "附件不能为空")
|
||||
private String video;
|
||||
|
||||
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
|
||||
@NotEmpty(message = "备注不能为空")
|
||||
private String memo;
|
||||
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
package cn.iocoder.yudao.module.infra.service.demo;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
|
||||
/**
|
||||
* 学生 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface InfraStudentService {
|
||||
|
||||
/**
|
||||
* 创建学生
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createStudent(@Valid InfraStudentSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新学生
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除学生
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteStudent(Long id);
|
||||
|
||||
/**
|
||||
* 获得学生
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 学生
|
||||
*/
|
||||
InfraStudentDO getStudent(Long id);
|
||||
|
||||
/**
|
||||
* 获得学生分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 学生分页
|
||||
*/
|
||||
PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO);
|
||||
|
||||
// ==================== 子表(学生联系人) ====================
|
||||
|
||||
/**
|
||||
* 获得学生联系人分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @param studentId 学生编号
|
||||
* @return 学生联系人分页
|
||||
*/
|
||||
PageResult<InfraStudentContactDO> getStudentContactPage(PageParam pageReqVO, Long studentId);
|
||||
|
||||
/**
|
||||
* 创建学生联系人
|
||||
*
|
||||
* @param studentContact 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createStudentContact(@Valid InfraStudentContactDO studentContact);
|
||||
|
||||
/**
|
||||
* 更新学生联系人
|
||||
*
|
||||
* @param studentContact 更新信息
|
||||
*/
|
||||
void updateStudentContact(@Valid InfraStudentContactDO studentContact);
|
||||
|
||||
/**
|
||||
* 删除学生联系人
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteStudentContact(Long id);
|
||||
|
||||
/**
|
||||
* 获得学生联系人
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 学生联系人
|
||||
*/
|
||||
InfraStudentContactDO getStudentContact(Long id);
|
||||
|
||||
// ==================== 子表(学生班主任) ====================
|
||||
|
||||
/**
|
||||
* 获得学生班主任分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @param studentId 学生编号
|
||||
* @return 学生班主任分页
|
||||
*/
|
||||
PageResult<InfraStudentTeacherDO> getStudentTeacherPage(PageParam pageReqVO, Long studentId);
|
||||
|
||||
/**
|
||||
* 创建学生班主任
|
||||
*
|
||||
* @param studentTeacher 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createStudentTeacher(@Valid InfraStudentTeacherDO studentTeacher);
|
||||
|
||||
/**
|
||||
* 更新学生班主任
|
||||
*
|
||||
* @param studentTeacher 更新信息
|
||||
*/
|
||||
void updateStudentTeacher(@Valid InfraStudentTeacherDO studentTeacher);
|
||||
|
||||
/**
|
||||
* 删除学生班主任
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteStudentTeacher(Long id);
|
||||
|
||||
/**
|
||||
* 获得学生班主任
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 学生班主任
|
||||
*/
|
||||
InfraStudentTeacherDO getStudentTeacher(Long id);
|
||||
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
package cn.iocoder.yudao.module.infra.service.demo;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 学生 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class InfraStudentServiceImpl implements InfraStudentService {
|
||||
|
||||
@Resource
|
||||
private InfraStudentMapper studentMapper;
|
||||
@Resource
|
||||
private InfraStudentContactMapper studentContactMapper;
|
||||
@Resource
|
||||
private InfraStudentTeacherMapper studentTeacherMapper;
|
||||
|
||||
@Override
|
||||
public Long createStudent(InfraStudentSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class);
|
||||
studentMapper.insert(student);
|
||||
// 返回
|
||||
return student.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStudent(InfraStudentSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateStudentExists(updateReqVO.getId());
|
||||
// 更新
|
||||
InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class);
|
||||
studentMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteStudent(Long id) {
|
||||
// 校验存在
|
||||
validateStudentExists(id);
|
||||
// 删除
|
||||
studentMapper.deleteById(id);
|
||||
|
||||
// 删除子表
|
||||
deleteStudentContactByStudentId(id);
|
||||
deleteStudentTeacherByStudentId(id);
|
||||
}
|
||||
|
||||
private void validateStudentExists(Long id) {
|
||||
if (studentMapper.selectById(id) == null) {
|
||||
throw exception(STUDENT_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InfraStudentDO getStudent(Long id) {
|
||||
return studentMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) {
|
||||
return studentMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
// ==================== 子表(学生联系人) ====================
|
||||
|
||||
@Override
|
||||
public PageResult<InfraStudentContactDO> getStudentContactPage(PageParam pageReqVO, Long studentId) {
|
||||
return studentContactMapper.selectPage(pageReqVO, studentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long createStudentContact(InfraStudentContactDO studentContact) {
|
||||
studentContactMapper.insert(studentContact);
|
||||
return studentContact.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStudentContact(InfraStudentContactDO studentContact) {
|
||||
// 校验存在
|
||||
validateStudentContactExists(studentContact.getId());
|
||||
// 更新
|
||||
studentContactMapper.updateById(studentContact);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteStudentContact(Long id) {
|
||||
// 校验存在
|
||||
validateStudentContactExists(id);
|
||||
// 删除
|
||||
studentContactMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InfraStudentContactDO getStudentContact(Long id) {
|
||||
return studentContactMapper.selectById(id);
|
||||
}
|
||||
|
||||
private void validateStudentContactExists(Long id) {
|
||||
if (studentContactMapper.selectById(id) == null) {
|
||||
throw exception(STUDENT_CONTACT_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteStudentContactByStudentId(Long studentId) {
|
||||
studentContactMapper.deleteByStudentId(studentId);
|
||||
}
|
||||
|
||||
// ==================== 子表(学生班主任) ====================
|
||||
|
||||
@Override
|
||||
public PageResult<InfraStudentTeacherDO> getStudentTeacherPage(PageParam pageReqVO, Long studentId) {
|
||||
return studentTeacherMapper.selectPage(pageReqVO, studentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long createStudentTeacher(InfraStudentTeacherDO studentTeacher) {
|
||||
// 校验是否已经存在
|
||||
if (studentTeacherMapper.selectByStudentId(studentTeacher.getStudentId()) != null) {
|
||||
throw exception(STUDENT_TEACHER_EXISTS);
|
||||
}
|
||||
// 插入
|
||||
studentTeacherMapper.insert(studentTeacher);
|
||||
return studentTeacher.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStudentTeacher(InfraStudentTeacherDO studentTeacher) {
|
||||
// 校验存在
|
||||
validateStudentTeacherExists(studentTeacher.getId());
|
||||
// 更新
|
||||
studentTeacherMapper.updateById(studentTeacher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteStudentTeacher(Long id) {
|
||||
// 校验存在
|
||||
validateStudentTeacherExists(id);
|
||||
// 删除
|
||||
studentTeacherMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InfraStudentTeacherDO getStudentTeacher(Long id) {
|
||||
return studentTeacherMapper.selectById(id);
|
||||
}
|
||||
|
||||
private void validateStudentTeacherExists(Long id) {
|
||||
if (studentTeacherMapper.selectById(id) == null) {
|
||||
throw exception(STUDENT_TEACHER_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteStudentTeacherByStudentId(Long studentId) {
|
||||
studentTeacherMapper.deleteByStudentId(studentId);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
package cn.iocoder.yudao.module.infra.service.demo;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.hutool.core.util.RandomUtil.*;
|
||||
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* {@link InfraStudentServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Import(InfraStudentServiceImpl.class)
|
||||
public class InfraStudentServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private InfraStudentServiceImpl studentService;
|
||||
|
||||
@Resource
|
||||
private InfraStudentMapper studentMapper;
|
||||
|
||||
@Test
|
||||
public void testCreateStudent_success() {
|
||||
// 准备参数
|
||||
InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null);
|
||||
|
||||
// 调用
|
||||
Long studentId = studentService.createStudent(createReqVO);
|
||||
// 断言
|
||||
assertNotNull(studentId);
|
||||
// 校验记录的属性是否正确
|
||||
InfraStudentDO student = studentMapper.selectById(studentId);
|
||||
assertPojoEquals(createReqVO, student, "id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateStudent_success() {
|
||||
// mock 数据
|
||||
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
|
||||
studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> {
|
||||
o.setId(dbStudent.getId()); // 设置更新的 ID
|
||||
});
|
||||
|
||||
// 调用
|
||||
studentService.updateStudent(updateReqVO);
|
||||
// 校验是否更新正确
|
||||
InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的
|
||||
assertPojoEquals(updateReqVO, student);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateStudent_notExists() {
|
||||
// 准备参数
|
||||
InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class);
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteStudent_success() {
|
||||
// mock 数据
|
||||
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
|
||||
studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
Long id = dbStudent.getId();
|
||||
|
||||
// 调用
|
||||
studentService.deleteStudent(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(studentMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteStudent_notExists() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
|
||||
public void testGetStudentPage() {
|
||||
// mock 数据
|
||||
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到
|
||||
o.setName(null);
|
||||
o.setBirthday(null);
|
||||
o.setSex(null);
|
||||
o.setEnabled(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
studentMapper.insert(dbStudent);
|
||||
// 测试 name 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null)));
|
||||
// 测试 birthday 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null)));
|
||||
// 测试 sex 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null)));
|
||||
// 测试 enabled 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null)));
|
||||
// 测试 createTime 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null)));
|
||||
// 准备参数
|
||||
InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO();
|
||||
reqVO.setName(null);
|
||||
reqVO.setBirthday(null);
|
||||
reqVO.setSex(null);
|
||||
reqVO.setEnabled(null);
|
||||
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
|
||||
|
||||
// 调用
|
||||
PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbStudent, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 学生班主任 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_student_teacher")
|
||||
@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class InfraStudentTeacherDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 学生编号
|
||||
*/
|
||||
private Long studentId;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 简介
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 出生日期
|
||||
*/
|
||||
private LocalDateTime birthday;
|
||||
/**
|
||||
* 性别
|
||||
*
|
||||
* 枚举 {@link TODO system_user_sex 对应的类}
|
||||
*/
|
||||
private Integer sex;
|
||||
/**
|
||||
* 是否有效
|
||||
*
|
||||
* 枚举 {@link TODO infra_boolean_string 对应的类}
|
||||
*/
|
||||
private Boolean enabled;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
/**
|
||||
* 附件
|
||||
*/
|
||||
private String video;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 学生班主任 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface InfraStudentTeacherMapper extends BaseMapperX<InfraStudentTeacherDO> {
|
||||
|
||||
default PageResult<InfraStudentTeacherDO> selectPage(PageParam reqVO, Long studentId) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentTeacherDO>()
|
||||
.eq(InfraStudentTeacherDO::getStudentId, studentId)
|
||||
.orderByDesc(InfraStudentTeacherDO::getId));
|
||||
}
|
||||
|
||||
default int deleteByStudentId(Long studentId) {
|
||||
return delete(InfraStudentTeacherDO::getStudentId, studentId);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里
|
||||
CREATE TABLE IF NOT EXISTS "infra_student" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"name" varchar NOT NULL,
|
||||
"description" varchar NOT NULL,
|
||||
"birthday" varchar NOT NULL,
|
||||
"sex" int NOT NULL,
|
||||
"enabled" bit NOT NULL,
|
||||
"avatar" varchar NOT NULL,
|
||||
"video" varchar NOT NULL,
|
||||
"memo" varchar NOT NULL,
|
||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '学生表';
|
||||
|
||||
-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里
|
||||
DELETE FROM "infra_student";
|
|
@ -4,8 +4,8 @@ INSERT INTO system_menu(
|
|||
path, icon, component, status, component_name
|
||||
)
|
||||
VALUES (
|
||||
'用户管理', '', 2, 0, 10,
|
||||
'user', '', 'system/user/index', 0, 'SystemUser'
|
||||
'学生管理', '', 2, 0, 888,
|
||||
'student', '', 'infra/demo/index', 0, 'InfraStudent'
|
||||
);
|
||||
|
||||
-- 按钮父菜单ID
|
||||
|
@ -18,7 +18,7 @@ INSERT INTO system_menu(
|
|||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'用户查询', 'system:user:query', 3, 1, @parentId,
|
||||
'学生查询', 'infra:student:query', 3, 1, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
||||
INSERT INTO system_menu(
|
||||
|
@ -26,7 +26,7 @@ INSERT INTO system_menu(
|
|||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'用户创建', 'system:user:create', 3, 2, @parentId,
|
||||
'学生创建', 'infra:student:create', 3, 2, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
||||
INSERT INTO system_menu(
|
||||
|
@ -34,7 +34,7 @@ INSERT INTO system_menu(
|
|||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'用户更新', 'system:user:update', 3, 3, @parentId,
|
||||
'学生更新', 'infra:student:update', 3, 3, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
||||
INSERT INTO system_menu(
|
||||
|
@ -42,7 +42,7 @@ INSERT INTO system_menu(
|
|||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'用户删除', 'system:user:delete', 3, 4, @parentId,
|
||||
'学生删除', 'infra:student:delete', 3, 4, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
||||
INSERT INTO system_menu(
|
||||
|
@ -50,6 +50,6 @@ INSERT INTO system_menu(
|
|||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'用户导出', 'system:user:export', 3, 5, @parentId,
|
||||
'学生导出', 'infra:student:export', 3, 5, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
|
@ -0,0 +1,95 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
export interface StudentVO {
|
||||
id: number
|
||||
name: string
|
||||
description: string
|
||||
birthday: Date
|
||||
sex: number
|
||||
enabled: boolean
|
||||
avatar: string
|
||||
video: string
|
||||
memo: string
|
||||
}
|
||||
|
||||
// 查询学生分页
|
||||
export const getStudentPage = async (params) => {
|
||||
return await request.get({ url: `/infra/student/page`, params })
|
||||
}
|
||||
|
||||
// 查询学生详情
|
||||
export const getStudent = async (id: number) => {
|
||||
return await request.get({ url: `/infra/student/get?id=` + id })
|
||||
}
|
||||
|
||||
// 新增学生
|
||||
export const createStudent = async (data: StudentVO) => {
|
||||
return await request.post({ url: `/infra/student/create`, data })
|
||||
}
|
||||
|
||||
// 修改学生
|
||||
export const updateStudent = async (data: StudentVO) => {
|
||||
return await request.put({ url: `/infra/student/update`, data })
|
||||
}
|
||||
|
||||
// 删除学生
|
||||
export const deleteStudent = async (id: number) => {
|
||||
return await request.delete({ url: `/infra/student/delete?id=` + id })
|
||||
}
|
||||
|
||||
// 导出学生 Excel
|
||||
export const exportStudent = async (params) => {
|
||||
return await request.download({ url: `/infra/student/export-excel`, params })
|
||||
}
|
||||
|
||||
// ==================== 子表(学生联系人) ====================
|
||||
|
||||
// 获得学生联系人分页
|
||||
export const getStudentContactPage = async (params) => {
|
||||
return await request.get({ url: `/infra/student/student-contact/page`, params })
|
||||
}
|
||||
// 新增学生联系人
|
||||
export const createStudentContact = async (data) => {
|
||||
return await request.post({ url: `/infra/student/student-contact/create`, data })
|
||||
}
|
||||
|
||||
// 修改学生联系人
|
||||
export const updateStudentContact = async (data) => {
|
||||
return await request.put({ url: `/infra/student/student-contact/update`, data })
|
||||
}
|
||||
|
||||
// 删除学生联系人
|
||||
export const deleteStudentContact = async (id: number) => {
|
||||
return await request.delete({ url: `/infra/student/student-contact/delete?id=` + id })
|
||||
}
|
||||
|
||||
// 获得学生联系人
|
||||
export const getStudentContact = async (id: number) => {
|
||||
return await request.get({ url: `/infra/student/student-contact/get?id=` + id })
|
||||
}
|
||||
|
||||
// ==================== 子表(学生班主任) ====================
|
||||
|
||||
// 获得学生班主任分页
|
||||
export const getStudentTeacherPage = async (params) => {
|
||||
return await request.get({ url: `/infra/student/student-teacher/page`, params })
|
||||
}
|
||||
// 新增学生班主任
|
||||
export const createStudentTeacher = async (data) => {
|
||||
return await request.post({ url: `/infra/student/student-teacher/create`, data })
|
||||
}
|
||||
|
||||
// 修改学生班主任
|
||||
export const updateStudentTeacher = async (data) => {
|
||||
return await request.put({ url: `/infra/student/student-teacher/update`, data })
|
||||
}
|
||||
|
||||
// 删除学生班主任
|
||||
export const deleteStudentTeacher = async (id: number) => {
|
||||
return await request.delete({ url: `/infra/student/student-teacher/delete?id=` + id })
|
||||
}
|
||||
|
||||
// 获得学生班主任
|
||||
export const getStudentTeacher = async (id: number) => {
|
||||
return await request.get({ url: `/infra/student/student-teacher/get?id=` + id })
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-form-item label="名字" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入名字" />
|
||||
</el-form-item>
|
||||
<el-form-item label="简介" prop="description">
|
||||
<el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
|
||||
</el-form-item>
|
||||
<el-form-item label="出生日期" prop="birthday">
|
||||
<el-date-picker
|
||||
v-model="formData.birthday"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择出生日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别" prop="sex">
|
||||
<el-select v-model="formData.sex" placeholder="请选择性别">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否有效" prop="enabled">
|
||||
<el-radio-group v-model="formData.enabled">
|
||||
<el-radio
|
||||
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="头像" prop="avatar">
|
||||
<UploadImg v-model="formData.avatar" />
|
||||
</el-form-item>
|
||||
<el-form-item label="附件" prop="video">
|
||||
<UploadFile v-model="formData.video" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="memo">
|
||||
<Editor v-model="formData.memo" height="150px" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import * as StudentApi from '@/api/infra/demo'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
studentId: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
birthday: undefined,
|
||||
sex: undefined,
|
||||
enabled: undefined,
|
||||
avatar: undefined,
|
||||
video: undefined,
|
||||
memo: undefined
|
||||
})
|
||||
const formRules = reactive({
|
||||
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
|
||||
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
|
||||
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
|
||||
sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
|
||||
enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
|
||||
avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
|
||||
memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number, studentId: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
formData.value.studentId = studentId
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await StudentApi.getStudentContact(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
await formRef.value.validate()
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value
|
||||
if (formType.value === 'create') {
|
||||
await StudentApi.createStudentContact(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await StudentApi.updateStudentContact(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
studentId: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
birthday: undefined,
|
||||
sex: undefined,
|
||||
enabled: undefined,
|
||||
avatar: undefined,
|
||||
video: undefined,
|
||||
memo: undefined
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,146 @@
|
|||
<template>
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['infra:student:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="编号" align="center" prop="id" />
|
||||
<el-table-column label="名字" align="center" prop="name" />
|
||||
<el-table-column label="简介" align="center" prop="description" />
|
||||
<el-table-column
|
||||
label="出生日期"
|
||||
align="center"
|
||||
prop="birthday"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="性别" align="center" prop="sex">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否有效" align="center" prop="enabled">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="头像" align="center" prop="avatar" />
|
||||
<el-table-column label="附件" align="center" prop="video" />
|
||||
<el-table-column label="备注" align="center" prop="memo" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['infra:student:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['infra:student:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<StudentContactForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import * as StudentApi from '@/api/infra/demo'
|
||||
import StudentContactForm from './StudentContactForm.vue'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const props = defineProps<{
|
||||
studentId: undefined // 学生编号(主表的关联字段)
|
||||
}>()
|
||||
const loading = ref(false) // 列表的加载中
|
||||
const list = ref([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
studentId: undefined
|
||||
})
|
||||
|
||||
/** 监听主表的关联字段的变化,加载对应的子表数据 */
|
||||
watch(
|
||||
() => props.studentId,
|
||||
(val) => {
|
||||
queryParams.studentId = val
|
||||
handleQuery()
|
||||
},
|
||||
{ immediate: false }
|
||||
)
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await StudentApi.getStudentContactPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
if (!props.studentId) {
|
||||
message.error('请选择一个学生')
|
||||
return
|
||||
}
|
||||
formRef.value.open(type, id, props.studentId)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await StudentApi.deleteStudentContact(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
</script>
|
|
@ -10,40 +10,8 @@
|
|||
<el-form-item label="名字" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入名字" />
|
||||
</el-form-item>
|
||||
<el-form-item label="个人简介">
|
||||
<Editor v-model="formData.description" height="150px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="性别 1" prop="sex1">
|
||||
<el-select v-model="formData.sex1" placeholder="请选择性别 1">
|
||||
<el-option
|
||||
v-for="dict in getStrDictOptions(DICT_TYPE.SYSTEM_SEX1)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别 2" prop="sex2">
|
||||
<el-checkbox-group v-model="formData.sex2">
|
||||
<el-checkbox
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_SEX2)"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别 3" prop="sex3">
|
||||
<el-radio-group v-model="formData.sex3">
|
||||
<el-radio
|
||||
v-for="dict in getBoolDictOptions(DICT_TYPE.SYSTEM_SEX3)"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<el-form-item label="简介" prop="description">
|
||||
<el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
|
||||
</el-form-item>
|
||||
<el-form-item label="出生日期" prop="birthday">
|
||||
<el-date-picker
|
||||
|
@ -53,16 +21,35 @@
|
|||
placeholder="选择出生日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="memo">
|
||||
<el-input v-model="formData.memo" type="textarea" placeholder="请输入备注" />
|
||||
<el-form-item label="性别" prop="sex">
|
||||
<el-select v-model="formData.sex" placeholder="请选择性别">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="formData.createTime"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择创建时间"
|
||||
/>
|
||||
<el-form-item label="是否有效" prop="enabled">
|
||||
<el-radio-group v-model="formData.enabled">
|
||||
<el-radio
|
||||
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="头像" prop="avatar">
|
||||
<UploadImg v-model="formData.avatar" />
|
||||
</el-form-item>
|
||||
<el-form-item label="附件" prop="video">
|
||||
<UploadFile v-model="formData.video" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="memo">
|
||||
<Editor v-model="formData.memo" height="150px" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
|
@ -72,8 +59,8 @@
|
|||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { DICT_TYPE, getStrDictOptions, getIntDictOptions, getBoolDictOptions } from '@/utils/dict'
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import * as StudentApi from '@/api/infra/demo'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
@ -85,18 +72,23 @@ const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
|||
const formData = ref({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
birthday: undefined,
|
||||
sex: undefined,
|
||||
enabled: undefined,
|
||||
avatar: undefined,
|
||||
video: undefined,
|
||||
description: undefined,
|
||||
sex1: undefined,
|
||||
sex2: [],
|
||||
sex3: undefined,
|
||||
birthday: undefined,
|
||||
memo: undefined,
|
||||
createTime: undefined
|
||||
memo: undefined
|
||||
})
|
||||
const formRules = reactive({
|
||||
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }]
|
||||
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
|
||||
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
|
||||
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
|
||||
sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
|
||||
enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
|
||||
avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
|
||||
video: [{ required: true, message: '附件不能为空', trigger: 'blur' }],
|
||||
memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
|
@ -110,7 +102,7 @@ const open = async (type: string, id?: number) => {
|
|||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await UserApi.getUser(id)
|
||||
formData.value = await StudentApi.getStudent(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
|
@ -122,18 +114,16 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
|||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
await formRef.value.validate()
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as UserApi.UserVO
|
||||
const data = formData.value as unknown as StudentApi.StudentVO
|
||||
if (formType.value === 'create') {
|
||||
await UserApi.createUser(data)
|
||||
await StudentApi.createStudent(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await UserApi.updateUser(data)
|
||||
await StudentApi.updateStudent(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
|
@ -149,15 +139,13 @@ const resetForm = () => {
|
|||
formData.value = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
birthday: undefined,
|
||||
sex: undefined,
|
||||
enabled: undefined,
|
||||
avatar: undefined,
|
||||
video: undefined,
|
||||
description: undefined,
|
||||
sex1: undefined,
|
||||
sex2: [],
|
||||
sex3: undefined,
|
||||
birthday: undefined,
|
||||
memo: undefined,
|
||||
createTime: undefined
|
||||
memo: undefined
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-form-item label="名字" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入名字" />
|
||||
</el-form-item>
|
||||
<el-form-item label="简介" prop="description">
|
||||
<el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
|
||||
</el-form-item>
|
||||
<el-form-item label="出生日期" prop="birthday">
|
||||
<el-date-picker
|
||||
v-model="formData.birthday"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择出生日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别" prop="sex">
|
||||
<el-select v-model="formData.sex" placeholder="请选择性别">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否有效" prop="enabled">
|
||||
<el-radio-group v-model="formData.enabled">
|
||||
<el-radio
|
||||
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="头像" prop="avatar">
|
||||
<UploadImg v-model="formData.avatar" />
|
||||
</el-form-item>
|
||||
<el-form-item label="附件" prop="video">
|
||||
<UploadFile v-model="formData.video" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="memo">
|
||||
<Editor v-model="formData.memo" height="150px" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import * as StudentApi from '@/api/infra/demo'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
studentId: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
birthday: undefined,
|
||||
sex: undefined,
|
||||
enabled: undefined,
|
||||
avatar: undefined,
|
||||
video: undefined,
|
||||
memo: undefined
|
||||
})
|
||||
const formRules = reactive({
|
||||
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
|
||||
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
|
||||
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
|
||||
sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
|
||||
enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
|
||||
avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
|
||||
memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number, studentId: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
formData.value.studentId = studentId
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await StudentApi.getStudentTeacher(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
await formRef.value.validate()
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value
|
||||
if (formType.value === 'create') {
|
||||
await StudentApi.createStudentTeacher(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await StudentApi.updateStudentTeacher(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
studentId: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
birthday: undefined,
|
||||
sex: undefined,
|
||||
enabled: undefined,
|
||||
avatar: undefined,
|
||||
video: undefined,
|
||||
memo: undefined
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,146 @@
|
|||
<template>
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['infra:student:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="编号" align="center" prop="id" />
|
||||
<el-table-column label="名字" align="center" prop="name" />
|
||||
<el-table-column label="简介" align="center" prop="description" />
|
||||
<el-table-column
|
||||
label="出生日期"
|
||||
align="center"
|
||||
prop="birthday"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="性别" align="center" prop="sex">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否有效" align="center" prop="enabled">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="头像" align="center" prop="avatar" />
|
||||
<el-table-column label="附件" align="center" prop="video" />
|
||||
<el-table-column label="备注" align="center" prop="memo" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['infra:student:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['infra:student:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<StudentTeacherForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import * as StudentApi from '@/api/infra/demo'
|
||||
import StudentTeacherForm from './StudentTeacherForm.vue'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const props = defineProps<{
|
||||
studentId: undefined // 学生编号(主表的关联字段)
|
||||
}>()
|
||||
const loading = ref(false) // 列表的加载中
|
||||
const list = ref([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
studentId: undefined
|
||||
})
|
||||
|
||||
/** 监听主表的关联字段的变化,加载对应的子表数据 */
|
||||
watch(
|
||||
() => props.studentId,
|
||||
(val) => {
|
||||
queryParams.studentId = val
|
||||
handleQuery()
|
||||
},
|
||||
{ immediate: false }
|
||||
)
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await StudentApi.getStudentTeacherPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
if (!props.studentId) {
|
||||
message.error('请选择一个学生')
|
||||
return
|
||||
}
|
||||
formRef.value.open(type, id, props.studentId)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await StudentApi.deleteStudentTeacher(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,278 @@
|
|||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="名字" prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="请输入名字"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="出生日期" prop="birthday">
|
||||
<el-date-picker
|
||||
v-model="queryParams.birthday"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="date"
|
||||
placeholder="选择出生日期"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别" prop="sex">
|
||||
<el-select
|
||||
v-model="queryParams.sex"
|
||||
placeholder="请选择性别"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否有效" prop="enabled">
|
||||
<el-select
|
||||
v-model="queryParams.enabled"
|
||||
placeholder="请选择是否有效"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['infra:student:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['infra:student:export']"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="list"
|
||||
:stripe="true"
|
||||
:show-overflow-tooltip="true"
|
||||
highlight-current-row
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<el-table-column label="编号" align="center" prop="id" />
|
||||
<el-table-column label="名字" align="center" prop="name" />
|
||||
<el-table-column label="简介" align="center" prop="description" />
|
||||
<el-table-column
|
||||
label="出生日期"
|
||||
align="center"
|
||||
prop="birthday"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="性别" align="center" prop="sex">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否有效" align="center" prop="enabled">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="头像" align="center" prop="avatar" />
|
||||
<el-table-column label="附件" align="center" prop="video" />
|
||||
<el-table-column label="备注" align="center" prop="memo" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['infra:student:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['infra:student:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<StudentForm ref="formRef" @success="getList" />
|
||||
<!-- 子表的列表 -->
|
||||
<ContentWrap>
|
||||
<el-tabs model-value="studentContact">
|
||||
<el-tab-pane label="学生联系人" name="studentContact">
|
||||
<StudentContactList :student-id="currentRow.id" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="学生班主任" name="studentTeacher">
|
||||
<StudentTeacherList :student-id="currentRow.id" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import * as StudentApi from '@/api/infra/demo'
|
||||
import StudentForm from './StudentForm.vue'
|
||||
import StudentContactList from './components/StudentContactList.vue'
|
||||
import StudentTeacherList from './components/StudentTeacherList.vue'
|
||||
|
||||
defineOptions({ name: 'InfraStudent' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
birthday: null,
|
||||
birthday: [],
|
||||
sex: null,
|
||||
enabled: null,
|
||||
createTime: []
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await StudentApi.getStudentPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await StudentApi.deleteStudent(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await StudentApi.exportStudent(queryParams)
|
||||
download.excel(data, '学生.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 选中行操作 */
|
||||
const currentRow = ref({}) // 选中行
|
||||
const handleCurrentChange = (row) => {
|
||||
currentRow.value = row
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.yudao.module.system.dal.mysql.user.SystemUserMapper">
|
||||
<mapper namespace="cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper">
|
||||
|
||||
<!--
|
||||
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
|
|
@ -0,0 +1,73 @@
|
|||
[ {
|
||||
"contentPath" : "java/InfraStudentPageReqVO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentRespVO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentSaveReqVO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentController",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentDO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentContactDO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentTeacherDO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentMapper",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentContactMapper",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentTeacherMapper",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java"
|
||||
}, {
|
||||
"contentPath" : "xml/InfraStudentMapper",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentServiceImpl",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentService",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentServiceImplTest",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java"
|
||||
}, {
|
||||
"contentPath" : "java/ErrorCodeConstants_手动操作",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java"
|
||||
}, {
|
||||
"contentPath" : "sql/sql",
|
||||
"filePath" : "sql/sql.sql"
|
||||
}, {
|
||||
"contentPath" : "sql/h2",
|
||||
"filePath" : "sql/h2.sql"
|
||||
}, {
|
||||
"contentPath" : "vue/index",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue"
|
||||
}, {
|
||||
"contentPath" : "vue/StudentForm",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/StudentForm.vue"
|
||||
}, {
|
||||
"contentPath" : "vue/StudentContactForm",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactForm.vue"
|
||||
}, {
|
||||
"contentPath" : "vue/StudentTeacherForm",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherForm.vue"
|
||||
}, {
|
||||
"contentPath" : "vue/StudentContactList",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactList.vue"
|
||||
}, {
|
||||
"contentPath" : "vue/StudentTeacherList",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherList.vue"
|
||||
}, {
|
||||
"contentPath" : "ts/index",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts"
|
||||
} ]
|
|
@ -0,0 +1,3 @@
|
|||
// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!!
|
||||
// ========== 学生 TODO 补充编号 ==========
|
||||
ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在");
|
|
@ -0,0 +1,71 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 学生联系人 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_student_contact")
|
||||
@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class InfraStudentContactDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 学生编号
|
||||
*/
|
||||
private Long studentId;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 简介
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 出生日期
|
||||
*/
|
||||
private LocalDateTime birthday;
|
||||
/**
|
||||
* 性别
|
||||
*
|
||||
* 枚举 {@link TODO system_user_sex 对应的类}
|
||||
*/
|
||||
private Integer sex;
|
||||
/**
|
||||
* 是否有效
|
||||
*
|
||||
* 枚举 {@link TODO infra_boolean_string 对应的类}
|
||||
*/
|
||||
private Boolean enabled;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
/**
|
||||
* 附件
|
||||
*/
|
||||
private String video;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 学生联系人 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface InfraStudentContactMapper extends BaseMapperX<InfraStudentContactDO> {
|
||||
|
||||
default List<InfraStudentContactDO> selectListByStudentId(Long studentId) {
|
||||
return selectList(InfraStudentContactDO::getStudentId, studentId);
|
||||
}
|
||||
|
||||
default int deleteByStudentId(Long studentId) {
|
||||
return delete(InfraStudentContactDO::getStudentId, studentId);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package cn.iocoder.yudao.module.infra.controller.admin.demo;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
import javax.validation.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService;
|
||||
|
||||
@Tag(name = "管理后台 - 学生")
|
||||
@RestController
|
||||
@RequestMapping("/infra/student")
|
||||
@Validated
|
||||
public class InfraStudentController {
|
||||
|
||||
@Resource
|
||||
private InfraStudentService studentService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建学生")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:create')")
|
||||
public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) {
|
||||
return success(studentService.createStudent(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新学生")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:update')")
|
||||
public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) {
|
||||
studentService.updateStudent(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除学生")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:delete')")
|
||||
public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) {
|
||||
studentService.deleteStudent(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得学生")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) {
|
||||
InfraStudentDO student = studentService.getStudent(id);
|
||||
return success(BeanUtils.toBean(student, InfraStudentRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得学生分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) {
|
||||
PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出学生 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class,
|
||||
BeanUtils.toBean(list, InfraStudentRespVO.class));
|
||||
}
|
||||
|
||||
// ==================== 子表(学生联系人) ====================
|
||||
|
||||
@GetMapping("/student-contact/list-by-student-id")
|
||||
@Operation(summary = "获得学生联系人列表")
|
||||
@Parameter(name = "studentId", description = "学生编号")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<List<InfraStudentContactDO>> getStudentContactListByStudentId(@RequestParam("studentId") Long studentId) {
|
||||
return success(studentService.getStudentContactListByStudentId(studentId));
|
||||
}
|
||||
|
||||
// ==================== 子表(学生班主任) ====================
|
||||
|
||||
@GetMapping("/student-teacher/get-by-student-id")
|
||||
@Operation(summary = "获得学生班主任")
|
||||
@Parameter(name = "studentId", description = "学生编号")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<InfraStudentTeacherDO> getStudentTeacherByStudentId(@RequestParam("studentId") Long studentId) {
|
||||
return success(studentService.getStudentTeacherByStudentId(studentId));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 学生 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_student")
|
||||
@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class InfraStudentDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 简介
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 出生日期
|
||||
*/
|
||||
private LocalDateTime birthday;
|
||||
/**
|
||||
* 性别
|
||||
*
|
||||
* 枚举 {@link TODO system_user_sex 对应的类}
|
||||
*/
|
||||
private Integer sex;
|
||||
/**
|
||||
* 是否有效
|
||||
*
|
||||
* 枚举 {@link TODO infra_boolean_string 对应的类}
|
||||
*/
|
||||
private Boolean enabled;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
/**
|
||||
* 附件
|
||||
*/
|
||||
private String video;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
|
||||
/**
|
||||
* 学生 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> {
|
||||
|
||||
default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>()
|
||||
.likeIfPresent(InfraStudentDO::getName, reqVO.getName())
|
||||
.eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday())
|
||||
.eqIfPresent(InfraStudentDO::getSex, reqVO.getSex())
|
||||
.eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled())
|
||||
.betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(InfraStudentDO::getId));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,33 +1,32 @@
|
|||
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import java.time.LocalDateTime;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 用户 Excel 导出 Request VO,参数和 SystemUserPageReqVO 是一致的")
|
||||
@Schema(description = "管理后台 - 学生分页 Request VO")
|
||||
@Data
|
||||
public class SystemUserExportReqVO {
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class InfraStudentPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "名字", example = "芋头")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "性别 1", example = "男")
|
||||
private String sex1;
|
||||
|
||||
@Schema(description = "性别 2", example = "1")
|
||||
private Integer sex2;
|
||||
|
||||
@Schema(description = "性别 3", example = "true")
|
||||
private Boolean sex3;
|
||||
|
||||
@Schema(description = "出生日期")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "性别", example = "1")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "是否有效", example = "true")
|
||||
private Boolean enabled;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
|
@ -0,0 +1,60 @@
|
|||
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.excel.annotation.*;
|
||||
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||
|
||||
@Schema(description = "管理后台 - 学生 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class InfraStudentRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@ExcelProperty("编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
|
||||
@ExcelProperty("名字")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
|
||||
@ExcelProperty("简介")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("出生日期")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty(value = "性别", converter = DictConvert.class)
|
||||
@DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@ExcelProperty(value = "是否有效", converter = DictConvert.class)
|
||||
@DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Boolean enabled;
|
||||
|
||||
@Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
||||
@ExcelProperty("头像")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
|
||||
@ExcelProperty("附件")
|
||||
private String video;
|
||||
|
||||
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
|
||||
@ExcelProperty("备注")
|
||||
private String memo;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import javax.validation.constraints.*;
|
||||
import java.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
|
||||
@Schema(description = "管理后台 - 学生新增/修改 Request VO")
|
||||
@Data
|
||||
public class InfraStudentSaveReqVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
|
||||
@NotEmpty(message = "名字不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
|
||||
@NotEmpty(message = "简介不能为空")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "出生日期不能为空")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "性别不能为空")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@NotNull(message = "是否有效不能为空")
|
||||
private Boolean enabled;
|
||||
|
||||
@Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
||||
@NotEmpty(message = "头像不能为空")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
|
||||
@NotEmpty(message = "附件不能为空")
|
||||
private String video;
|
||||
|
||||
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
|
||||
@NotEmpty(message = "备注不能为空")
|
||||
private String memo;
|
||||
|
||||
@Schema(description = "学生联系人列表")
|
||||
private List<InfraStudentContactDO> studentContacts;
|
||||
|
||||
@Schema(description = "学生班主任")
|
||||
private InfraStudentTeacherDO studentTeacher;
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package cn.iocoder.yudao.module.infra.service.demo;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
|
||||
/**
|
||||
* 学生 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface InfraStudentService {
|
||||
|
||||
/**
|
||||
* 创建学生
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createStudent(@Valid InfraStudentSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新学生
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除学生
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteStudent(Long id);
|
||||
|
||||
/**
|
||||
* 获得学生
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 学生
|
||||
*/
|
||||
InfraStudentDO getStudent(Long id);
|
||||
|
||||
/**
|
||||
* 获得学生分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 学生分页
|
||||
*/
|
||||
PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO);
|
||||
|
||||
// ==================== 子表(学生联系人) ====================
|
||||
|
||||
/**
|
||||
* 获得学生联系人列表
|
||||
*
|
||||
* @param studentId 学生编号
|
||||
* @return 学生联系人列表
|
||||
*/
|
||||
List<InfraStudentContactDO> getStudentContactListByStudentId(Long studentId);
|
||||
|
||||
// ==================== 子表(学生班主任) ====================
|
||||
|
||||
/**
|
||||
* 获得学生班主任
|
||||
*
|
||||
* @param studentId 学生编号
|
||||
* @return 学生班主任
|
||||
*/
|
||||
InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId);
|
||||
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
package cn.iocoder.yudao.module.infra.service.demo;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 学生 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class InfraStudentServiceImpl implements InfraStudentService {
|
||||
|
||||
@Resource
|
||||
private InfraStudentMapper studentMapper;
|
||||
@Resource
|
||||
private InfraStudentContactMapper studentContactMapper;
|
||||
@Resource
|
||||
private InfraStudentTeacherMapper studentTeacherMapper;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createStudent(InfraStudentSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class);
|
||||
studentMapper.insert(student);
|
||||
|
||||
// 插入子表
|
||||
createStudentContactList(student.getId(), createReqVO.getStudentContacts());
|
||||
createStudentTeacher(student.getId(), createReqVO.getStudentTeacher());
|
||||
// 返回
|
||||
return student.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateStudent(InfraStudentSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateStudentExists(updateReqVO.getId());
|
||||
// 更新
|
||||
InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class);
|
||||
studentMapper.updateById(updateObj);
|
||||
|
||||
// 更新子表
|
||||
updateStudentContactList(updateReqVO.getId(), updateReqVO.getStudentContacts());
|
||||
updateStudentTeacher(updateReqVO.getId(), updateReqVO.getStudentTeacher());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteStudent(Long id) {
|
||||
// 校验存在
|
||||
validateStudentExists(id);
|
||||
// 删除
|
||||
studentMapper.deleteById(id);
|
||||
|
||||
// 删除子表
|
||||
deleteStudentContactByStudentId(id);
|
||||
deleteStudentTeacherByStudentId(id);
|
||||
}
|
||||
|
||||
private void validateStudentExists(Long id) {
|
||||
if (studentMapper.selectById(id) == null) {
|
||||
throw exception(STUDENT_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InfraStudentDO getStudent(Long id) {
|
||||
return studentMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) {
|
||||
return studentMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
// ==================== 子表(学生联系人) ====================
|
||||
|
||||
@Override
|
||||
public List<InfraStudentContactDO> getStudentContactListByStudentId(Long studentId) {
|
||||
return studentContactMapper.selectListByStudentId(studentId);
|
||||
}
|
||||
|
||||
private void createStudentContactList(Long studentId, List<InfraStudentContactDO> list) {
|
||||
list.forEach(o -> o.setStudentId(studentId));
|
||||
studentContactMapper.insertBatch(list);
|
||||
}
|
||||
|
||||
private void updateStudentContactList(Long studentId, List<InfraStudentContactDO> list) {
|
||||
deleteStudentContactByStudentId(studentId);
|
||||
list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新
|
||||
createStudentContactList(studentId, list);
|
||||
}
|
||||
|
||||
private void deleteStudentContactByStudentId(Long studentId) {
|
||||
studentContactMapper.deleteByStudentId(studentId);
|
||||
}
|
||||
|
||||
// ==================== 子表(学生班主任) ====================
|
||||
|
||||
@Override
|
||||
public InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId) {
|
||||
return studentTeacherMapper.selectByStudentId(studentId);
|
||||
}
|
||||
|
||||
private void createStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) {
|
||||
if (studentTeacher == null) {
|
||||
return;
|
||||
}
|
||||
studentTeacher.setStudentId(studentId);
|
||||
studentTeacherMapper.insert(studentTeacher);
|
||||
}
|
||||
|
||||
private void updateStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) {
|
||||
if (studentTeacher == null) {
|
||||
return;
|
||||
}
|
||||
studentTeacher.setStudentId(studentId);
|
||||
studentTeacher.setUpdater(null).setUpdateTime(null); // 解决更新情况下:updateTime 不更新
|
||||
studentTeacherMapper.insertOrUpdate(studentTeacher);
|
||||
}
|
||||
|
||||
private void deleteStudentTeacherByStudentId(Long studentId) {
|
||||
studentTeacherMapper.deleteByStudentId(studentId);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
package cn.iocoder.yudao.module.infra.service.demo;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.hutool.core.util.RandomUtil.*;
|
||||
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* {@link InfraStudentServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Import(InfraStudentServiceImpl.class)
|
||||
public class InfraStudentServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private InfraStudentServiceImpl studentService;
|
||||
|
||||
@Resource
|
||||
private InfraStudentMapper studentMapper;
|
||||
|
||||
@Test
|
||||
public void testCreateStudent_success() {
|
||||
// 准备参数
|
||||
InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null);
|
||||
|
||||
// 调用
|
||||
Long studentId = studentService.createStudent(createReqVO);
|
||||
// 断言
|
||||
assertNotNull(studentId);
|
||||
// 校验记录的属性是否正确
|
||||
InfraStudentDO student = studentMapper.selectById(studentId);
|
||||
assertPojoEquals(createReqVO, student, "id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateStudent_success() {
|
||||
// mock 数据
|
||||
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
|
||||
studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> {
|
||||
o.setId(dbStudent.getId()); // 设置更新的 ID
|
||||
});
|
||||
|
||||
// 调用
|
||||
studentService.updateStudent(updateReqVO);
|
||||
// 校验是否更新正确
|
||||
InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的
|
||||
assertPojoEquals(updateReqVO, student);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateStudent_notExists() {
|
||||
// 准备参数
|
||||
InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class);
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteStudent_success() {
|
||||
// mock 数据
|
||||
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
|
||||
studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
Long id = dbStudent.getId();
|
||||
|
||||
// 调用
|
||||
studentService.deleteStudent(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(studentMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteStudent_notExists() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
|
||||
public void testGetStudentPage() {
|
||||
// mock 数据
|
||||
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到
|
||||
o.setName(null);
|
||||
o.setBirthday(null);
|
||||
o.setSex(null);
|
||||
o.setEnabled(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
studentMapper.insert(dbStudent);
|
||||
// 测试 name 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null)));
|
||||
// 测试 birthday 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null)));
|
||||
// 测试 sex 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null)));
|
||||
// 测试 enabled 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null)));
|
||||
// 测试 createTime 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null)));
|
||||
// 准备参数
|
||||
InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO();
|
||||
reqVO.setName(null);
|
||||
reqVO.setBirthday(null);
|
||||
reqVO.setSex(null);
|
||||
reqVO.setEnabled(null);
|
||||
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
|
||||
|
||||
// 调用
|
||||
PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbStudent, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 学生班主任 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_student_teacher")
|
||||
@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class InfraStudentTeacherDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 学生编号
|
||||
*/
|
||||
private Long studentId;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 简介
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 出生日期
|
||||
*/
|
||||
private LocalDateTime birthday;
|
||||
/**
|
||||
* 性别
|
||||
*
|
||||
* 枚举 {@link TODO system_user_sex 对应的类}
|
||||
*/
|
||||
private Integer sex;
|
||||
/**
|
||||
* 是否有效
|
||||
*
|
||||
* 枚举 {@link TODO infra_boolean_string 对应的类}
|
||||
*/
|
||||
private Boolean enabled;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
/**
|
||||
* 附件
|
||||
*/
|
||||
private String video;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 学生班主任 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface InfraStudentTeacherMapper extends BaseMapperX<InfraStudentTeacherDO> {
|
||||
|
||||
default InfraStudentTeacherDO selectByStudentId(Long studentId) {
|
||||
return selectOne(InfraStudentTeacherDO::getStudentId, studentId);
|
||||
}
|
||||
|
||||
default int deleteByStudentId(Long studentId) {
|
||||
return delete(InfraStudentTeacherDO::getStudentId, studentId);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里
|
||||
CREATE TABLE IF NOT EXISTS "infra_student" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"name" varchar NOT NULL,
|
||||
"description" varchar NOT NULL,
|
||||
"birthday" varchar NOT NULL,
|
||||
"sex" int NOT NULL,
|
||||
"enabled" bit NOT NULL,
|
||||
"avatar" varchar NOT NULL,
|
||||
"video" varchar NOT NULL,
|
||||
"memo" varchar NOT NULL,
|
||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '学生表';
|
||||
|
||||
-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里
|
||||
DELETE FROM "infra_student";
|
|
@ -0,0 +1,55 @@
|
|||
-- 菜单 SQL
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status, component_name
|
||||
)
|
||||
VALUES (
|
||||
'学生管理', '', 2, 0, 888,
|
||||
'student', '', 'infra/demo/index', 0, 'InfraStudent'
|
||||
);
|
||||
|
||||
-- 按钮父菜单ID
|
||||
-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
|
||||
SELECT @parentId := LAST_INSERT_ID();
|
||||
|
||||
-- 按钮 SQL
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'学生查询', 'infra:student:query', 3, 1, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'学生创建', 'infra:student:create', 3, 2, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'学生更新', 'infra:student:update', 3, 3, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'学生删除', 'infra:student:delete', 3, 4, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'学生导出', 'infra:student:export', 3, 5, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
|
@ -0,0 +1,57 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
export interface StudentVO {
|
||||
id: number
|
||||
name: string
|
||||
description: string
|
||||
birthday: Date
|
||||
sex: number
|
||||
enabled: boolean
|
||||
avatar: string
|
||||
video: string
|
||||
memo: string
|
||||
}
|
||||
|
||||
// 查询学生分页
|
||||
export const getStudentPage = async (params) => {
|
||||
return await request.get({ url: `/infra/student/page`, params })
|
||||
}
|
||||
|
||||
// 查询学生详情
|
||||
export const getStudent = async (id: number) => {
|
||||
return await request.get({ url: `/infra/student/get?id=` + id })
|
||||
}
|
||||
|
||||
// 新增学生
|
||||
export const createStudent = async (data: StudentVO) => {
|
||||
return await request.post({ url: `/infra/student/create`, data })
|
||||
}
|
||||
|
||||
// 修改学生
|
||||
export const updateStudent = async (data: StudentVO) => {
|
||||
return await request.put({ url: `/infra/student/update`, data })
|
||||
}
|
||||
|
||||
// 删除学生
|
||||
export const deleteStudent = async (id: number) => {
|
||||
return await request.delete({ url: `/infra/student/delete?id=` + id })
|
||||
}
|
||||
|
||||
// 导出学生 Excel
|
||||
export const exportStudent = async (params) => {
|
||||
return await request.download({ url: `/infra/student/export-excel`, params })
|
||||
}
|
||||
|
||||
// ==================== 子表(学生联系人) ====================
|
||||
|
||||
// 获得学生联系人列表
|
||||
export const getStudentContactListByStudentId = async (studentId) => {
|
||||
return await request.get({ url: `/infra/student/student-contact/list-by-student-id?studentId=` + studentId })
|
||||
}
|
||||
|
||||
// ==================== 子表(学生班主任) ====================
|
||||
|
||||
// 获得学生班主任
|
||||
export const getStudentTeacherByStudentId = async (studentId) => {
|
||||
return await request.get({ url: `/infra/student/student-teacher/get-by-student-id?studentId=` + studentId })
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
<template>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
v-loading="formLoading"
|
||||
label-width="0px"
|
||||
:inline-message="true"
|
||||
>
|
||||
<el-table :data="formData" class="-mt-10px">
|
||||
<el-table-column label="序号" type="index" width="100" />
|
||||
<el-table-column label="名字" min-width="150">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.name`" :rules="formRules.name" class="mb-0px!">
|
||||
<el-input v-model="row.name" placeholder="请输入名字" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="简介" min-width="200">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.description`" :rules="formRules.description" class="mb-0px!">
|
||||
<el-input v-model="row.description" type="textarea" placeholder="请输入简介" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="出生日期" min-width="150">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.birthday`" :rules="formRules.birthday" class="mb-0px!">
|
||||
<el-date-picker
|
||||
v-model="row.birthday"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择出生日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="性别" min-width="150">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.sex`" :rules="formRules.sex" class="mb-0px!">
|
||||
<el-select v-model="row.sex" placeholder="请选择性别">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否有效" min-width="150">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.enabled`" :rules="formRules.enabled" class="mb-0px!">
|
||||
<el-radio-group v-model="row.enabled">
|
||||
<el-radio
|
||||
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="头像" min-width="200">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.avatar`" :rules="formRules.avatar" class="mb-0px!">
|
||||
<UploadImg v-model="row.avatar" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件" min-width="200">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.video`" :rules="formRules.video" class="mb-0px!">
|
||||
<UploadFile v-model="row.video" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="400">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.memo`" :rules="formRules.memo" class="mb-0px!">
|
||||
<Editor v-model="row.memo" height="150px" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" fixed="right" label="操作" width="60">
|
||||
<template #default="{ $index }">
|
||||
<el-button @click="handleDelete($index)" link>—</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
<el-row justify="center" class="mt-3">
|
||||
<el-button @click="handleAdd" round>+ 添加学生联系人</el-button>
|
||||
</el-row>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import * as StudentApi from '@/api/infra/demo'
|
||||
|
||||
const props = defineProps<{
|
||||
studentId: undefined // 学生编号(主表的关联字段)
|
||||
}>()
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formData = ref([])
|
||||
const formRules = reactive({
|
||||
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
|
||||
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
|
||||
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
|
||||
sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
|
||||
enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
|
||||
avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
|
||||
memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 监听主表的关联字段的变化,加载对应的子表数据 */
|
||||
watch(
|
||||
() => props.studentId,
|
||||
async (val) => {
|
||||
// 1. 重置表单
|
||||
formData.value = []
|
||||
// 2. val 非空,则加载数据
|
||||
if (!val) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
formLoading.value = true
|
||||
formData.value = await StudentApi.getStudentContactListByStudentId(val)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = () => {
|
||||
const row = {
|
||||
id: undefined,
|
||||
studentId: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
birthday: undefined,
|
||||
sex: undefined,
|
||||
enabled: undefined,
|
||||
avatar: undefined,
|
||||
video: undefined,
|
||||
memo: undefined
|
||||
}
|
||||
row.studentId = props.studentId
|
||||
formData.value.push(row)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = (index) => {
|
||||
formData.value.splice(index, 1)
|
||||
}
|
||||
|
||||
/** 表单校验 */
|
||||
const validate = () => {
|
||||
return formRef.value.validate()
|
||||
}
|
||||
|
||||
/** 表单值 */
|
||||
const getData = () => {
|
||||
return formData.value
|
||||
}
|
||||
|
||||
defineExpose({ validate, getData })
|
||||
</script>
|
|
@ -0,0 +1,72 @@
|
|||
<template>
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="编号" align="center" prop="id" />
|
||||
<el-table-column label="名字" align="center" prop="name" />
|
||||
<el-table-column label="简介" align="center" prop="description" />
|
||||
<el-table-column
|
||||
label="出生日期"
|
||||
align="center"
|
||||
prop="birthday"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="性别" align="center" prop="sex">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否有效" align="center" prop="enabled">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="头像" align="center" prop="avatar" />
|
||||
<el-table-column label="附件" align="center" prop="video" />
|
||||
<el-table-column label="备注" align="center" prop="memo" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
</el-table>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import * as StudentApi from '@/api/infra/demo'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const props = defineProps<{
|
||||
studentId: undefined // 学生编号(主表的关联字段)
|
||||
}>()
|
||||
const loading = ref(false) // 列表的加载中
|
||||
const list = ref([]) // 列表的数据
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
list.value = await StudentApi.getStudentContactListByStudentId(props.studentId)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
|
@ -0,0 +1,184 @@
|
|||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-form-item label="名字" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入名字" />
|
||||
</el-form-item>
|
||||
<el-form-item label="简介" prop="description">
|
||||
<el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
|
||||
</el-form-item>
|
||||
<el-form-item label="出生日期" prop="birthday">
|
||||
<el-date-picker
|
||||
v-model="formData.birthday"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择出生日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别" prop="sex">
|
||||
<el-select v-model="formData.sex" placeholder="请选择性别">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否有效" prop="enabled">
|
||||
<el-radio-group v-model="formData.enabled">
|
||||
<el-radio
|
||||
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="头像" prop="avatar">
|
||||
<UploadImg v-model="formData.avatar" />
|
||||
</el-form-item>
|
||||
<el-form-item label="附件" prop="video">
|
||||
<UploadFile v-model="formData.video" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="memo">
|
||||
<Editor v-model="formData.memo" height="150px" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 子表的表单 -->
|
||||
<el-tabs v-model="subTabsName">
|
||||
<el-tab-pane label="学生联系人" name="studentContact">
|
||||
<StudentContactForm ref="studentContactFormRef" :student-id="formData.id" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="学生班主任" name="studentTeacher">
|
||||
<StudentTeacherForm ref="studentTeacherFormRef" :student-id="formData.id" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import * as StudentApi from '@/api/infra/demo'
|
||||
import StudentContactForm from './components/StudentContactForm.vue'
|
||||
import StudentTeacherForm from './components/StudentTeacherForm.vue'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
birthday: undefined,
|
||||
sex: undefined,
|
||||
enabled: undefined,
|
||||
avatar: undefined,
|
||||
video: undefined,
|
||||
memo: undefined
|
||||
})
|
||||
const formRules = reactive({
|
||||
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
|
||||
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
|
||||
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
|
||||
sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
|
||||
enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
|
||||
avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
|
||||
video: [{ required: true, message: '附件不能为空', trigger: 'blur' }],
|
||||
memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 子表的表单 */
|
||||
const subTabsName = ref('studentContact')
|
||||
const studentContactFormRef = ref()
|
||||
const studentTeacherFormRef = ref()
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await StudentApi.getStudent(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
await formRef.value.validate()
|
||||
// 校验子表单
|
||||
try {
|
||||
await studentContactFormRef.value.validate()
|
||||
} catch (e) {
|
||||
subTabsName.value = 'studentContact'
|
||||
return
|
||||
}
|
||||
try {
|
||||
await studentTeacherFormRef.value.validate()
|
||||
} catch (e) {
|
||||
subTabsName.value = 'studentTeacher'
|
||||
return
|
||||
}
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as StudentApi.StudentVO
|
||||
// 拼接子表的数据
|
||||
data.studentContacts = studentContactFormRef.value.getData()
|
||||
data.studentTeacher = studentTeacherFormRef.value.getData()
|
||||
if (formType.value === 'create') {
|
||||
await StudentApi.createStudent(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await StudentApi.updateStudent(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
birthday: undefined,
|
||||
sex: undefined,
|
||||
enabled: undefined,
|
||||
avatar: undefined,
|
||||
video: undefined,
|
||||
memo: undefined
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,122 @@
|
|||
<template>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-form-item label="名字" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入名字" />
|
||||
</el-form-item>
|
||||
<el-form-item label="简介" prop="description">
|
||||
<el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
|
||||
</el-form-item>
|
||||
<el-form-item label="出生日期" prop="birthday">
|
||||
<el-date-picker
|
||||
v-model="formData.birthday"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择出生日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别" prop="sex">
|
||||
<el-select v-model="formData.sex" placeholder="请选择性别">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否有效" prop="enabled">
|
||||
<el-radio-group v-model="formData.enabled">
|
||||
<el-radio
|
||||
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="头像" prop="avatar">
|
||||
<UploadImg v-model="formData.avatar" />
|
||||
</el-form-item>
|
||||
<el-form-item label="附件" prop="video">
|
||||
<UploadFile v-model="formData.video" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="memo">
|
||||
<Editor v-model="formData.memo" height="150px" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import * as StudentApi from '@/api/infra/demo'
|
||||
|
||||
const props = defineProps<{
|
||||
studentId: undefined // 学生编号(主表的关联字段)
|
||||
}>()
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formData = ref([])
|
||||
const formRules = reactive({
|
||||
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
|
||||
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
|
||||
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
|
||||
sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
|
||||
enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
|
||||
avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
|
||||
memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 监听主表的关联字段的变化,加载对应的子表数据 */
|
||||
watch(
|
||||
() => props.studentId,
|
||||
async (val) => {
|
||||
// 1. 重置表单
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
studentId: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
birthday: undefined,
|
||||
sex: undefined,
|
||||
enabled: undefined,
|
||||
avatar: undefined,
|
||||
video: undefined,
|
||||
memo: undefined,
|
||||
}
|
||||
// 2. val 非空,则加载数据
|
||||
if (!val) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
formLoading.value = true
|
||||
const data = await StudentApi.getStudentTeacherByStudentId(val)
|
||||
if (!data) {
|
||||
return
|
||||
}
|
||||
formData.value = data
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
/** 表单校验 */
|
||||
const validate = () => {
|
||||
return formRef.value.validate()
|
||||
}
|
||||
|
||||
/** 表单值 */
|
||||
const getData = () => {
|
||||
return formData.value
|
||||
}
|
||||
|
||||
defineExpose({ validate, getData })
|
||||
</script>
|
|
@ -0,0 +1,76 @@
|
|||
<template>
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="编号" align="center" prop="id" />
|
||||
<el-table-column label="名字" align="center" prop="name" />
|
||||
<el-table-column label="简介" align="center" prop="description" />
|
||||
<el-table-column
|
||||
label="出生日期"
|
||||
align="center"
|
||||
prop="birthday"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="性别" align="center" prop="sex">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否有效" align="center" prop="enabled">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="头像" align="center" prop="avatar" />
|
||||
<el-table-column label="附件" align="center" prop="video" />
|
||||
<el-table-column label="备注" align="center" prop="memo" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
</el-table>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import * as StudentApi from '@/api/infra/demo'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const props = defineProps<{
|
||||
studentId: undefined // 学生编号(主表的关联字段)
|
||||
}>()
|
||||
const loading = ref(false) // 列表的加载中
|
||||
const list = ref([]) // 列表的数据
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await StudentApi.getStudentTeacherByStudentId(props.studentId)
|
||||
if (!data) {
|
||||
return
|
||||
}
|
||||
list.value.push(data)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
|
@ -17,26 +17,6 @@
|
|||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别 1" prop="sex1">
|
||||
<el-select v-model="queryParams.sex1" placeholder="请选择性别 1" clearable class="!w-240px">
|
||||
<el-option
|
||||
v-for="dict in getStrDictOptions(DICT_TYPE.SYSTEM_SEX1)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别 3" prop="sex3">
|
||||
<el-select v-model="queryParams.sex3" placeholder="请选择性别 3" clearable class="!w-240px">
|
||||
<el-option
|
||||
v-for="dict in getBoolDictOptions(DICT_TYPE.SYSTEM_SEX3)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="出生日期" prop="birthday">
|
||||
<el-date-picker
|
||||
v-model="queryParams.birthday"
|
||||
|
@ -47,6 +27,36 @@
|
|||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别" prop="sex">
|
||||
<el-select
|
||||
v-model="queryParams.sex"
|
||||
placeholder="请选择性别"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否有效" prop="enabled">
|
||||
<el-select
|
||||
v-model="queryParams.enabled"
|
||||
placeholder="请选择是否有效"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
|
@ -61,7 +71,12 @@
|
|||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button type="primary" @click="openForm('create')" v-hasPermi="['system:user:create']">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['infra:student:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
|
@ -69,7 +84,7 @@
|
|||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['system:user:export']"
|
||||
v-hasPermi="['infra:student:export']"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||
</el-button>
|
||||
|
@ -80,46 +95,22 @@
|
|||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="编号" align="center" prop="id">
|
||||
<!-- 子表的列表 -->
|
||||
<el-table-column type="expand">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.id" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="名字" align="center" prop="name">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.name" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="头像" align="center" prop="avatar">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.avatar" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="视频" align="center" prop="video">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.video" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="个人简介" align="center" prop="description">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.description" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="性别 1" align="center" prop="sex1">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.SYSTEM_SEX1" :value="scope.row.sex1" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="性别 2" align="center" prop="sex2">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.SYSTEM_SEX2" :value="scope.row.sex2" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="性别 3" align="center" prop="sex3">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.SYSTEM_SEX3" :value="scope.row.sex3" />
|
||||
<el-tabs model-value="studentContact">
|
||||
<el-tab-pane label="学生联系人" name="studentContact">
|
||||
<StudentContactList :student-id="scope.row.id" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="学生班主任" name="studentTeacher">
|
||||
<StudentTeacherList :student-id="scope.row.id" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="编号" align="center" prop="id" />
|
||||
<el-table-column label="名字" align="center" prop="name" />
|
||||
<el-table-column label="简介" align="center" prop="description" />
|
||||
<el-table-column
|
||||
label="出生日期"
|
||||
align="center"
|
||||
|
@ -127,11 +118,19 @@
|
|||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="备注" align="center" prop="memo">
|
||||
<el-table-column label="性别" align="center" prop="sex">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.memo" />
|
||||
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否有效" align="center" prop="enabled">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="头像" align="center" prop="avatar" />
|
||||
<el-table-column label="附件" align="center" prop="video" />
|
||||
<el-table-column label="备注" align="center" prop="memo" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
|
@ -145,7 +144,7 @@
|
|||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['system:user:update']"
|
||||
v-hasPermi="['infra:student:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
|
@ -153,7 +152,7 @@
|
|||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['system:user:delete']"
|
||||
v-hasPermi="['infra:student:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
|
@ -170,33 +169,34 @@
|
|||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<UserForm ref="formRef" @success="getList" />
|
||||
<StudentForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { DICT_TYPE, getStrDictOptions, getBoolDictOptions } from '@/utils/dict'
|
||||
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import UserForm from './UserForm.vue'
|
||||
import * as StudentApi from '@/api/infra/demo'
|
||||
import StudentForm from './StudentForm.vue'
|
||||
import StudentContactList from './components/StudentContactList.vue'
|
||||
import StudentTeacherList from './components/StudentTeacherList.vue'
|
||||
|
||||
defineOptions({ name: 'SystemUser' })
|
||||
defineOptions({ name: 'InfraStudent' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
sex1: null,
|
||||
sex2: null,
|
||||
sex3: null,
|
||||
birthday: null,
|
||||
birthday: [],
|
||||
sex: null,
|
||||
enabled: null,
|
||||
createTime: []
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
|
@ -206,7 +206,7 @@ const exportLoading = ref(false) // 导出的加载中
|
|||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await UserApi.getUserPage(queryParams)
|
||||
const data = await StudentApi.getStudentPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
|
@ -238,7 +238,7 @@ const handleDelete = async (id: number) => {
|
|||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await UserApi.deleteUser(id)
|
||||
await StudentApi.deleteStudent(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
|
@ -252,8 +252,8 @@ const handleExport = async () => {
|
|||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await UserApi.exportUser(queryParams)
|
||||
download.excel(data, '用户.xls')
|
||||
const data = await StudentApi.exportStudent(queryParams)
|
||||
download.excel(data, '学生.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper">
|
||||
|
||||
<!--
|
||||
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
|
||||
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
|
||||
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
|
||||
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
|
||||
-->
|
||||
|
||||
</mapper>
|
|
@ -1,4 +1,67 @@
|
|||
[{
|
||||
"filePath": "",
|
||||
"contentPath": ""
|
||||
}]
|
||||
[ {
|
||||
"contentPath" : "java/InfraStudentPageReqVO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentRespVO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentSaveReqVO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentController",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentDO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentContactDO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentTeacherDO",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentMapper",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentContactMapper",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentTeacherMapper",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java"
|
||||
}, {
|
||||
"contentPath" : "xml/InfraStudentMapper",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentServiceImpl",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentService",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java"
|
||||
}, {
|
||||
"contentPath" : "java/InfraStudentServiceImplTest",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java"
|
||||
}, {
|
||||
"contentPath" : "java/ErrorCodeConstants_手动操作",
|
||||
"filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java"
|
||||
}, {
|
||||
"contentPath" : "sql/sql",
|
||||
"filePath" : "sql/sql.sql"
|
||||
}, {
|
||||
"contentPath" : "sql/h2",
|
||||
"filePath" : "sql/h2.sql"
|
||||
}, {
|
||||
"contentPath" : "vue/index",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue"
|
||||
}, {
|
||||
"contentPath" : "vue/StudentForm",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/StudentForm.vue"
|
||||
}, {
|
||||
"contentPath" : "vue/StudentContactForm",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactForm.vue"
|
||||
}, {
|
||||
"contentPath" : "vue/StudentTeacherForm",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherForm.vue"
|
||||
}, {
|
||||
"contentPath" : "ts/index",
|
||||
"filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts"
|
||||
} ]
|
|
@ -0,0 +1,3 @@
|
|||
// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!!
|
||||
// ========== 学生 TODO 补充编号 ==========
|
||||
ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在");
|
|
@ -0,0 +1,71 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 学生联系人 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_student_contact")
|
||||
@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class InfraStudentContactDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 学生编号
|
||||
*/
|
||||
private Long studentId;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 简介
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 出生日期
|
||||
*/
|
||||
private LocalDateTime birthday;
|
||||
/**
|
||||
* 性别
|
||||
*
|
||||
* 枚举 {@link TODO system_user_sex 对应的类}
|
||||
*/
|
||||
private Integer sex;
|
||||
/**
|
||||
* 是否有效
|
||||
*
|
||||
* 枚举 {@link TODO infra_boolean_string 对应的类}
|
||||
*/
|
||||
private Boolean enabled;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
/**
|
||||
* 附件
|
||||
*/
|
||||
private String video;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 学生联系人 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface InfraStudentContactMapper extends BaseMapperX<InfraStudentContactDO> {
|
||||
|
||||
default List<InfraStudentContactDO> selectListByStudentId(Long studentId) {
|
||||
return selectList(InfraStudentContactDO::getStudentId, studentId);
|
||||
}
|
||||
|
||||
default int deleteByStudentId(Long studentId) {
|
||||
return delete(InfraStudentContactDO::getStudentId, studentId);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package cn.iocoder.yudao.module.infra.controller.admin.demo;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
import javax.validation.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService;
|
||||
|
||||
@Tag(name = "管理后台 - 学生")
|
||||
@RestController
|
||||
@RequestMapping("/infra/student")
|
||||
@Validated
|
||||
public class InfraStudentController {
|
||||
|
||||
@Resource
|
||||
private InfraStudentService studentService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建学生")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:create')")
|
||||
public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) {
|
||||
return success(studentService.createStudent(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新学生")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:update')")
|
||||
public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) {
|
||||
studentService.updateStudent(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除学生")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:delete')")
|
||||
public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) {
|
||||
studentService.deleteStudent(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得学生")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) {
|
||||
InfraStudentDO student = studentService.getStudent(id);
|
||||
return success(BeanUtils.toBean(student, InfraStudentRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得学生分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) {
|
||||
PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出学生 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class,
|
||||
BeanUtils.toBean(list, InfraStudentRespVO.class));
|
||||
}
|
||||
|
||||
// ==================== 子表(学生联系人) ====================
|
||||
|
||||
@GetMapping("/student-contact/list-by-student-id")
|
||||
@Operation(summary = "获得学生联系人列表")
|
||||
@Parameter(name = "studentId", description = "学生编号")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<List<InfraStudentContactDO>> getStudentContactListByStudentId(@RequestParam("studentId") Long studentId) {
|
||||
return success(studentService.getStudentContactListByStudentId(studentId));
|
||||
}
|
||||
|
||||
// ==================== 子表(学生班主任) ====================
|
||||
|
||||
@GetMapping("/student-teacher/get-by-student-id")
|
||||
@Operation(summary = "获得学生班主任")
|
||||
@Parameter(name = "studentId", description = "学生编号")
|
||||
@PreAuthorize("@ss.hasPermission('infra:student:query')")
|
||||
public CommonResult<InfraStudentTeacherDO> getStudentTeacherByStudentId(@RequestParam("studentId") Long studentId) {
|
||||
return success(studentService.getStudentTeacherByStudentId(studentId));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 学生 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_student")
|
||||
@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class InfraStudentDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 简介
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 出生日期
|
||||
*/
|
||||
private LocalDateTime birthday;
|
||||
/**
|
||||
* 性别
|
||||
*
|
||||
* 枚举 {@link TODO system_user_sex 对应的类}
|
||||
*/
|
||||
private Integer sex;
|
||||
/**
|
||||
* 是否有效
|
||||
*
|
||||
* 枚举 {@link TODO infra_boolean_string 对应的类}
|
||||
*/
|
||||
private Boolean enabled;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
/**
|
||||
* 附件
|
||||
*/
|
||||
private String video;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
|
||||
/**
|
||||
* 学生 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> {
|
||||
|
||||
default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>()
|
||||
.likeIfPresent(InfraStudentDO::getName, reqVO.getName())
|
||||
.eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday())
|
||||
.eqIfPresent(InfraStudentDO::getSex, reqVO.getSex())
|
||||
.eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled())
|
||||
.betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(InfraStudentDO::getId));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 学生分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class InfraStudentPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "名字", example = "芋头")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "出生日期")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "性别", example = "1")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "是否有效", example = "true")
|
||||
private Boolean enabled;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.excel.annotation.*;
|
||||
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||
|
||||
@Schema(description = "管理后台 - 学生 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class InfraStudentRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@ExcelProperty("编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
|
||||
@ExcelProperty("名字")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
|
||||
@ExcelProperty("简介")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("出生日期")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty(value = "性别", converter = DictConvert.class)
|
||||
@DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@ExcelProperty(value = "是否有效", converter = DictConvert.class)
|
||||
@DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Boolean enabled;
|
||||
|
||||
@Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
||||
@ExcelProperty("头像")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
|
||||
@ExcelProperty("附件")
|
||||
private String video;
|
||||
|
||||
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
|
||||
@ExcelProperty("备注")
|
||||
private String memo;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import javax.validation.constraints.*;
|
||||
import java.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
|
||||
@Schema(description = "管理后台 - 学生新增/修改 Request VO")
|
||||
@Data
|
||||
public class InfraStudentSaveReqVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
|
||||
@NotEmpty(message = "名字不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
|
||||
@NotEmpty(message = "简介不能为空")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "出生日期不能为空")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "性别不能为空")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@NotNull(message = "是否有效不能为空")
|
||||
private Boolean enabled;
|
||||
|
||||
@Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
||||
@NotEmpty(message = "头像不能为空")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
|
||||
@NotEmpty(message = "附件不能为空")
|
||||
private String video;
|
||||
|
||||
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
|
||||
@NotEmpty(message = "备注不能为空")
|
||||
private String memo;
|
||||
|
||||
@Schema(description = "学生联系人列表")
|
||||
private List<InfraStudentContactDO> studentContacts;
|
||||
|
||||
@Schema(description = "学生班主任")
|
||||
private InfraStudentTeacherDO studentTeacher;
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package cn.iocoder.yudao.module.infra.service.demo;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
|
||||
/**
|
||||
* 学生 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface InfraStudentService {
|
||||
|
||||
/**
|
||||
* 创建学生
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createStudent(@Valid InfraStudentSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新学生
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除学生
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteStudent(Long id);
|
||||
|
||||
/**
|
||||
* 获得学生
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 学生
|
||||
*/
|
||||
InfraStudentDO getStudent(Long id);
|
||||
|
||||
/**
|
||||
* 获得学生分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 学生分页
|
||||
*/
|
||||
PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO);
|
||||
|
||||
// ==================== 子表(学生联系人) ====================
|
||||
|
||||
/**
|
||||
* 获得学生联系人列表
|
||||
*
|
||||
* @param studentId 学生编号
|
||||
* @return 学生联系人列表
|
||||
*/
|
||||
List<InfraStudentContactDO> getStudentContactListByStudentId(Long studentId);
|
||||
|
||||
// ==================== 子表(学生班主任) ====================
|
||||
|
||||
/**
|
||||
* 获得学生班主任
|
||||
*
|
||||
* @param studentId 学生编号
|
||||
* @return 学生班主任
|
||||
*/
|
||||
InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId);
|
||||
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
package cn.iocoder.yudao.module.infra.service.demo;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 学生 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class InfraStudentServiceImpl implements InfraStudentService {
|
||||
|
||||
@Resource
|
||||
private InfraStudentMapper studentMapper;
|
||||
@Resource
|
||||
private InfraStudentContactMapper studentContactMapper;
|
||||
@Resource
|
||||
private InfraStudentTeacherMapper studentTeacherMapper;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createStudent(InfraStudentSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class);
|
||||
studentMapper.insert(student);
|
||||
|
||||
// 插入子表
|
||||
createStudentContactList(student.getId(), createReqVO.getStudentContacts());
|
||||
createStudentTeacher(student.getId(), createReqVO.getStudentTeacher());
|
||||
// 返回
|
||||
return student.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateStudent(InfraStudentSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateStudentExists(updateReqVO.getId());
|
||||
// 更新
|
||||
InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class);
|
||||
studentMapper.updateById(updateObj);
|
||||
|
||||
// 更新子表
|
||||
updateStudentContactList(updateReqVO.getId(), updateReqVO.getStudentContacts());
|
||||
updateStudentTeacher(updateReqVO.getId(), updateReqVO.getStudentTeacher());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteStudent(Long id) {
|
||||
// 校验存在
|
||||
validateStudentExists(id);
|
||||
// 删除
|
||||
studentMapper.deleteById(id);
|
||||
|
||||
// 删除子表
|
||||
deleteStudentContactByStudentId(id);
|
||||
deleteStudentTeacherByStudentId(id);
|
||||
}
|
||||
|
||||
private void validateStudentExists(Long id) {
|
||||
if (studentMapper.selectById(id) == null) {
|
||||
throw exception(STUDENT_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InfraStudentDO getStudent(Long id) {
|
||||
return studentMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) {
|
||||
return studentMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
// ==================== 子表(学生联系人) ====================
|
||||
|
||||
@Override
|
||||
public List<InfraStudentContactDO> getStudentContactListByStudentId(Long studentId) {
|
||||
return studentContactMapper.selectListByStudentId(studentId);
|
||||
}
|
||||
|
||||
private void createStudentContactList(Long studentId, List<InfraStudentContactDO> list) {
|
||||
list.forEach(o -> o.setStudentId(studentId));
|
||||
studentContactMapper.insertBatch(list);
|
||||
}
|
||||
|
||||
private void updateStudentContactList(Long studentId, List<InfraStudentContactDO> list) {
|
||||
deleteStudentContactByStudentId(studentId);
|
||||
list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新
|
||||
createStudentContactList(studentId, list);
|
||||
}
|
||||
|
||||
private void deleteStudentContactByStudentId(Long studentId) {
|
||||
studentContactMapper.deleteByStudentId(studentId);
|
||||
}
|
||||
|
||||
// ==================== 子表(学生班主任) ====================
|
||||
|
||||
@Override
|
||||
public InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId) {
|
||||
return studentTeacherMapper.selectByStudentId(studentId);
|
||||
}
|
||||
|
||||
private void createStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) {
|
||||
if (studentTeacher == null) {
|
||||
return;
|
||||
}
|
||||
studentTeacher.setStudentId(studentId);
|
||||
studentTeacherMapper.insert(studentTeacher);
|
||||
}
|
||||
|
||||
private void updateStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) {
|
||||
if (studentTeacher == null) {
|
||||
return;
|
||||
}
|
||||
studentTeacher.setStudentId(studentId);
|
||||
studentTeacher.setUpdater(null).setUpdateTime(null); // 解决更新情况下:updateTime 不更新
|
||||
studentTeacherMapper.insertOrUpdate(studentTeacher);
|
||||
}
|
||||
|
||||
private void deleteStudentTeacherByStudentId(Long studentId) {
|
||||
studentTeacherMapper.deleteByStudentId(studentId);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
package cn.iocoder.yudao.module.infra.service.demo;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.hutool.core.util.RandomUtil.*;
|
||||
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* {@link InfraStudentServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Import(InfraStudentServiceImpl.class)
|
||||
public class InfraStudentServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private InfraStudentServiceImpl studentService;
|
||||
|
||||
@Resource
|
||||
private InfraStudentMapper studentMapper;
|
||||
|
||||
@Test
|
||||
public void testCreateStudent_success() {
|
||||
// 准备参数
|
||||
InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null);
|
||||
|
||||
// 调用
|
||||
Long studentId = studentService.createStudent(createReqVO);
|
||||
// 断言
|
||||
assertNotNull(studentId);
|
||||
// 校验记录的属性是否正确
|
||||
InfraStudentDO student = studentMapper.selectById(studentId);
|
||||
assertPojoEquals(createReqVO, student, "id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateStudent_success() {
|
||||
// mock 数据
|
||||
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
|
||||
studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> {
|
||||
o.setId(dbStudent.getId()); // 设置更新的 ID
|
||||
});
|
||||
|
||||
// 调用
|
||||
studentService.updateStudent(updateReqVO);
|
||||
// 校验是否更新正确
|
||||
InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的
|
||||
assertPojoEquals(updateReqVO, student);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateStudent_notExists() {
|
||||
// 准备参数
|
||||
InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class);
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteStudent_success() {
|
||||
// mock 数据
|
||||
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
|
||||
studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
Long id = dbStudent.getId();
|
||||
|
||||
// 调用
|
||||
studentService.deleteStudent(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(studentMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteStudent_notExists() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
|
||||
public void testGetStudentPage() {
|
||||
// mock 数据
|
||||
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到
|
||||
o.setName(null);
|
||||
o.setBirthday(null);
|
||||
o.setSex(null);
|
||||
o.setEnabled(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
studentMapper.insert(dbStudent);
|
||||
// 测试 name 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null)));
|
||||
// 测试 birthday 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null)));
|
||||
// 测试 sex 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null)));
|
||||
// 测试 enabled 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null)));
|
||||
// 测试 createTime 不匹配
|
||||
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null)));
|
||||
// 准备参数
|
||||
InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO();
|
||||
reqVO.setName(null);
|
||||
reqVO.setBirthday(null);
|
||||
reqVO.setSex(null);
|
||||
reqVO.setEnabled(null);
|
||||
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
|
||||
|
||||
// 调用
|
||||
PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbStudent, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 学生班主任 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_student_teacher")
|
||||
@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class InfraStudentTeacherDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 学生编号
|
||||
*/
|
||||
private Long studentId;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 简介
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 出生日期
|
||||
*/
|
||||
private LocalDateTime birthday;
|
||||
/**
|
||||
* 性别
|
||||
*
|
||||
* 枚举 {@link TODO system_user_sex 对应的类}
|
||||
*/
|
||||
private Integer sex;
|
||||
/**
|
||||
* 是否有效
|
||||
*
|
||||
* 枚举 {@link TODO infra_boolean_string 对应的类}
|
||||
*/
|
||||
private Boolean enabled;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
/**
|
||||
* 附件
|
||||
*/
|
||||
private String video;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 学生班主任 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface InfraStudentTeacherMapper extends BaseMapperX<InfraStudentTeacherDO> {
|
||||
|
||||
default InfraStudentTeacherDO selectByStudentId(Long studentId) {
|
||||
return selectOne(InfraStudentTeacherDO::getStudentId, studentId);
|
||||
}
|
||||
|
||||
default int deleteByStudentId(Long studentId) {
|
||||
return delete(InfraStudentTeacherDO::getStudentId, studentId);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里
|
||||
CREATE TABLE IF NOT EXISTS "infra_student" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"name" varchar NOT NULL,
|
||||
"description" varchar NOT NULL,
|
||||
"birthday" varchar NOT NULL,
|
||||
"sex" int NOT NULL,
|
||||
"enabled" bit NOT NULL,
|
||||
"avatar" varchar NOT NULL,
|
||||
"video" varchar NOT NULL,
|
||||
"memo" varchar NOT NULL,
|
||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '学生表';
|
||||
|
||||
-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里
|
||||
DELETE FROM "infra_student";
|
|
@ -0,0 +1,55 @@
|
|||
-- 菜单 SQL
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status, component_name
|
||||
)
|
||||
VALUES (
|
||||
'学生管理', '', 2, 0, 888,
|
||||
'student', '', 'infra/demo/index', 0, 'InfraStudent'
|
||||
);
|
||||
|
||||
-- 按钮父菜单ID
|
||||
-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
|
||||
SELECT @parentId := LAST_INSERT_ID();
|
||||
|
||||
-- 按钮 SQL
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'学生查询', 'infra:student:query', 3, 1, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'学生创建', 'infra:student:create', 3, 2, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'学生更新', 'infra:student:update', 3, 3, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'学生删除', 'infra:student:delete', 3, 4, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'学生导出', 'infra:student:export', 3, 5, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
|
@ -0,0 +1,57 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
export interface StudentVO {
|
||||
id: number
|
||||
name: string
|
||||
description: string
|
||||
birthday: Date
|
||||
sex: number
|
||||
enabled: boolean
|
||||
avatar: string
|
||||
video: string
|
||||
memo: string
|
||||
}
|
||||
|
||||
// 查询学生分页
|
||||
export const getStudentPage = async (params) => {
|
||||
return await request.get({ url: `/infra/student/page`, params })
|
||||
}
|
||||
|
||||
// 查询学生详情
|
||||
export const getStudent = async (id: number) => {
|
||||
return await request.get({ url: `/infra/student/get?id=` + id })
|
||||
}
|
||||
|
||||
// 新增学生
|
||||
export const createStudent = async (data: StudentVO) => {
|
||||
return await request.post({ url: `/infra/student/create`, data })
|
||||
}
|
||||
|
||||
// 修改学生
|
||||
export const updateStudent = async (data: StudentVO) => {
|
||||
return await request.put({ url: `/infra/student/update`, data })
|
||||
}
|
||||
|
||||
// 删除学生
|
||||
export const deleteStudent = async (id: number) => {
|
||||
return await request.delete({ url: `/infra/student/delete?id=` + id })
|
||||
}
|
||||
|
||||
// 导出学生 Excel
|
||||
export const exportStudent = async (params) => {
|
||||
return await request.download({ url: `/infra/student/export-excel`, params })
|
||||
}
|
||||
|
||||
// ==================== 子表(学生联系人) ====================
|
||||
|
||||
// 获得学生联系人列表
|
||||
export const getStudentContactListByStudentId = async (studentId) => {
|
||||
return await request.get({ url: `/infra/student/student-contact/list-by-student-id?studentId=` + studentId })
|
||||
}
|
||||
|
||||
// ==================== 子表(学生班主任) ====================
|
||||
|
||||
// 获得学生班主任
|
||||
export const getStudentTeacherByStudentId = async (studentId) => {
|
||||
return await request.get({ url: `/infra/student/student-teacher/get-by-student-id?studentId=` + studentId })
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
<template>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
v-loading="formLoading"
|
||||
label-width="0px"
|
||||
:inline-message="true"
|
||||
>
|
||||
<el-table :data="formData" class="-mt-10px">
|
||||
<el-table-column label="序号" type="index" width="100" />
|
||||
<el-table-column label="名字" min-width="150">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.name`" :rules="formRules.name" class="mb-0px!">
|
||||
<el-input v-model="row.name" placeholder="请输入名字" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="简介" min-width="200">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.description`" :rules="formRules.description" class="mb-0px!">
|
||||
<el-input v-model="row.description" type="textarea" placeholder="请输入简介" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="出生日期" min-width="150">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.birthday`" :rules="formRules.birthday" class="mb-0px!">
|
||||
<el-date-picker
|
||||
v-model="row.birthday"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择出生日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="性别" min-width="150">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.sex`" :rules="formRules.sex" class="mb-0px!">
|
||||
<el-select v-model="row.sex" placeholder="请选择性别">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否有效" min-width="150">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.enabled`" :rules="formRules.enabled" class="mb-0px!">
|
||||
<el-radio-group v-model="row.enabled">
|
||||
<el-radio
|
||||
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="头像" min-width="200">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.avatar`" :rules="formRules.avatar" class="mb-0px!">
|
||||
<UploadImg v-model="row.avatar" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件" min-width="200">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.video`" :rules="formRules.video" class="mb-0px!">
|
||||
<UploadFile v-model="row.video" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="400">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.memo`" :rules="formRules.memo" class="mb-0px!">
|
||||
<Editor v-model="row.memo" height="150px" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" fixed="right" label="操作" width="60">
|
||||
<template #default="{ $index }">
|
||||
<el-button @click="handleDelete($index)" link>—</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
<el-row justify="center" class="mt-3">
|
||||
<el-button @click="handleAdd" round>+ 添加学生联系人</el-button>
|
||||
</el-row>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import * as StudentApi from '@/api/infra/demo'
|
||||
|
||||
const props = defineProps<{
|
||||
studentId: undefined // 学生编号(主表的关联字段)
|
||||
}>()
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formData = ref([])
|
||||
const formRules = reactive({
|
||||
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
|
||||
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
|
||||
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
|
||||
sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
|
||||
enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
|
||||
avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
|
||||
memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 监听主表的关联字段的变化,加载对应的子表数据 */
|
||||
watch(
|
||||
() => props.studentId,
|
||||
async (val) => {
|
||||
// 1. 重置表单
|
||||
formData.value = []
|
||||
// 2. val 非空,则加载数据
|
||||
if (!val) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
formLoading.value = true
|
||||
formData.value = await StudentApi.getStudentContactListByStudentId(val)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = () => {
|
||||
const row = {
|
||||
id: undefined,
|
||||
studentId: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
birthday: undefined,
|
||||
sex: undefined,
|
||||
enabled: undefined,
|
||||
avatar: undefined,
|
||||
video: undefined,
|
||||
memo: undefined
|
||||
}
|
||||
row.studentId = props.studentId
|
||||
formData.value.push(row)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = (index) => {
|
||||
formData.value.splice(index, 1)
|
||||
}
|
||||
|
||||
/** 表单校验 */
|
||||
const validate = () => {
|
||||
return formRef.value.validate()
|
||||
}
|
||||
|
||||
/** 表单值 */
|
||||
const getData = () => {
|
||||
return formData.value
|
||||
}
|
||||
|
||||
defineExpose({ validate, getData })
|
||||
</script>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue