初始化提交
This commit is contained in:
25
yudao-module-infra/pom.xml
Normal file
25
yudao-module-infra/pom.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<modules>
|
||||
<module>yudao-module-infra-api</module>
|
||||
<module>yudao-module-infra-biz</module>
|
||||
</modules>
|
||||
<artifactId>yudao-module-infra</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
infra 模块,主要提供两块能力:
|
||||
1. 我们放基础设施的运维与管理,支撑上层的通用与核心业务。 例如说:定时任务的管理、服务器的信息等等
|
||||
2. 研发工具,提升研发效率与质量。 例如说:代码生成器、接口文档等等
|
||||
</description>
|
||||
|
||||
</project>
|
33
yudao-module-infra/yudao-module-infra-api/pom.xml
Normal file
33
yudao-module-infra/yudao-module-infra-api/pom.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-infra</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>yudao-module-infra-api</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
infra 模块 API,暴露给其它模块调用
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 参数校验 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,41 @@
|
||||
package cn.iocoder.yudao.module.infra.api.file;
|
||||
|
||||
/**
|
||||
* 文件 API 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface FileApi {
|
||||
|
||||
/**
|
||||
* 保存文件,并返回文件的访问路径
|
||||
*
|
||||
* @param content 文件内容
|
||||
* @return 文件路径
|
||||
*/
|
||||
default String createFile(byte[] content) {
|
||||
return createFile(null, null, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件,并返回文件的访问路径
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param content 文件内容
|
||||
* @return 文件路径
|
||||
*/
|
||||
default String createFile(String path, byte[] content) {
|
||||
return createFile(null, path, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件,并返回文件的访问路径
|
||||
*
|
||||
* @param name 文件名称
|
||||
* @param path 文件路径
|
||||
* @param content 文件内容
|
||||
* @return 文件路径
|
||||
*/
|
||||
String createFile(String name, String path, byte[] content);
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.infra.api.logger;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* API 访问日志的 API 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface ApiAccessLogApi {
|
||||
|
||||
/**
|
||||
* 创建 API 访问日志
|
||||
*
|
||||
* @param createDTO 创建信息
|
||||
*/
|
||||
void createApiAccessLog(@Valid ApiAccessLogCreateReqDTO createDTO);
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.infra.api.logger;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* API 错误日志的 API 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface ApiErrorLogApi {
|
||||
|
||||
/**
|
||||
* 创建 API 错误日志
|
||||
*
|
||||
* @param createDTO 创建信息
|
||||
*/
|
||||
void createApiErrorLog(@Valid ApiErrorLogCreateReqDTO createDTO);
|
||||
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package cn.iocoder.yudao.module.infra.api.logger.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* API 访问日志
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class ApiAccessLogCreateReqDTO {
|
||||
|
||||
/**
|
||||
* 链路追踪编号
|
||||
*/
|
||||
private String traceId;
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
private Integer userType;
|
||||
/**
|
||||
* 应用名
|
||||
*/
|
||||
@NotNull(message = "应用名不能为空")
|
||||
private String applicationName;
|
||||
|
||||
/**
|
||||
* 请求方法名
|
||||
*/
|
||||
@NotNull(message = "http 请求方法不能为空")
|
||||
private String requestMethod;
|
||||
/**
|
||||
* 访问地址
|
||||
*/
|
||||
@NotNull(message = "访问地址不能为空")
|
||||
private String requestUrl;
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
@NotNull(message = "请求参数不能为空")
|
||||
private String requestParams;
|
||||
/**
|
||||
* 用户 IP
|
||||
*/
|
||||
@NotNull(message = "ip 不能为空")
|
||||
private String userIp;
|
||||
/**
|
||||
* 浏览器 UA
|
||||
*/
|
||||
@NotNull(message = "User-Agent 不能为空")
|
||||
private String userAgent;
|
||||
|
||||
/**
|
||||
* 开始请求时间
|
||||
*/
|
||||
@NotNull(message = "开始请求时间不能为空")
|
||||
private LocalDateTime beginTime;
|
||||
/**
|
||||
* 结束请求时间
|
||||
*/
|
||||
@NotNull(message = "结束请求时间不能为空")
|
||||
private LocalDateTime endTime;
|
||||
/**
|
||||
* 执行时长,单位:毫秒
|
||||
*/
|
||||
@NotNull(message = "执行时长不能为空")
|
||||
private Integer duration;
|
||||
/**
|
||||
* 结果码
|
||||
*/
|
||||
@NotNull(message = "错误码不能为空")
|
||||
private Integer resultCode;
|
||||
/**
|
||||
* 结果提示
|
||||
*/
|
||||
private String resultMsg;
|
||||
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
package cn.iocoder.yudao.module.infra.api.logger.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* API 错误日志
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class ApiErrorLogCreateReqDTO {
|
||||
|
||||
/**
|
||||
* 链路编号
|
||||
*/
|
||||
private String traceId;
|
||||
/**
|
||||
* 账号编号
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
private Integer userType;
|
||||
/**
|
||||
* 应用名
|
||||
*/
|
||||
@NotNull(message = "应用名不能为空")
|
||||
private String applicationName;
|
||||
|
||||
/**
|
||||
* 请求方法名
|
||||
*/
|
||||
@NotNull(message = "http 请求方法不能为空")
|
||||
private String requestMethod;
|
||||
/**
|
||||
* 访问地址
|
||||
*/
|
||||
@NotNull(message = "访问地址不能为空")
|
||||
private String requestUrl;
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
@NotNull(message = "请求参数不能为空")
|
||||
private String requestParams;
|
||||
/**
|
||||
* 用户 IP
|
||||
*/
|
||||
@NotNull(message = "ip 不能为空")
|
||||
private String userIp;
|
||||
/**
|
||||
* 浏览器 UA
|
||||
*/
|
||||
@NotNull(message = "User-Agent 不能为空")
|
||||
private String userAgent;
|
||||
|
||||
/**
|
||||
* 异常时间
|
||||
*/
|
||||
@NotNull(message = "异常时间不能为空")
|
||||
private LocalDateTime exceptionTime;
|
||||
/**
|
||||
* 异常名
|
||||
*/
|
||||
@NotNull(message = "异常名不能为空")
|
||||
private String exceptionName;
|
||||
/**
|
||||
* 异常发生的类全名
|
||||
*/
|
||||
@NotNull(message = "异常发生的类全名不能为空")
|
||||
private String exceptionClassName;
|
||||
/**
|
||||
* 异常发生的类文件
|
||||
*/
|
||||
@NotNull(message = "异常发生的类文件不能为空")
|
||||
private String exceptionFileName;
|
||||
/**
|
||||
* 异常发生的方法名
|
||||
*/
|
||||
@NotNull(message = "异常发生的方法名不能为空")
|
||||
private String exceptionMethodName;
|
||||
/**
|
||||
* 异常发生的方法所在行
|
||||
*/
|
||||
@NotNull(message = "异常发生的方法所在行不能为空")
|
||||
private Integer exceptionLineNumber;
|
||||
/**
|
||||
* 异常的栈轨迹异常的栈轨迹
|
||||
*/
|
||||
@NotNull(message = "异常的栈轨迹不能为空")
|
||||
private String exceptionStackTrace;
|
||||
/**
|
||||
* 异常导致的根消息
|
||||
*/
|
||||
@NotNull(message = "异常导致的根消息不能为空")
|
||||
private String exceptionRootCauseMessage;
|
||||
/**
|
||||
* 异常导致的消息
|
||||
*/
|
||||
@NotNull(message = "异常导致的消息不能为空")
|
||||
private String exceptionMessage;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* infra API 包,定义暴露给其它模块的 API
|
||||
*/
|
||||
package cn.iocoder.yudao.module.infra.api;
|
@ -0,0 +1,54 @@
|
||||
package cn.iocoder.yudao.module.infra.api.websocket;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
|
||||
/**
|
||||
* WebSocket 发送器的 API 接口
|
||||
*
|
||||
* 对 WebSocketMessageSender 进行封装,提供给其它模块使用
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface WebSocketSenderApi {
|
||||
|
||||
/**
|
||||
* 发送消息给指定用户
|
||||
*
|
||||
* @param userType 用户类型
|
||||
* @param userId 用户编号
|
||||
* @param messageType 消息类型
|
||||
* @param messageContent 消息内容,JSON 格式
|
||||
*/
|
||||
void send(Integer userType, Long userId, String messageType, String messageContent);
|
||||
|
||||
/**
|
||||
* 发送消息给指定用户类型
|
||||
*
|
||||
* @param userType 用户类型
|
||||
* @param messageType 消息类型
|
||||
* @param messageContent 消息内容,JSON 格式
|
||||
*/
|
||||
void send(Integer userType, String messageType, String messageContent);
|
||||
|
||||
/**
|
||||
* 发送消息给指定 Session
|
||||
*
|
||||
* @param sessionId Session 编号
|
||||
* @param messageType 消息类型
|
||||
* @param messageContent 消息内容,JSON 格式
|
||||
*/
|
||||
void send(String sessionId, String messageType, String messageContent);
|
||||
|
||||
default void sendObject(Integer userType, Long userId, String messageType, Object messageContent) {
|
||||
send(userType, userId, messageType, JsonUtils.toJsonString(messageContent));
|
||||
}
|
||||
|
||||
default void sendObject(Integer userType, String messageType, Object messageContent) {
|
||||
send(userType, messageType, JsonUtils.toJsonString(messageContent));
|
||||
}
|
||||
|
||||
default void sendObject(String sessionId, String messageType, Object messageContent) {
|
||||
send(sessionId, messageType, JsonUtils.toJsonString(messageContent));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.infra.enums;
|
||||
|
||||
/**
|
||||
* Infra 字典类型的枚举类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface DictTypeConstants {
|
||||
|
||||
String REDIS_TIMEOUT_TYPE = "infra_redis_timeout_type"; // Redis 超时类型
|
||||
|
||||
String JOB_STATUS = "infra_job_status"; // 定时任务状态的枚举
|
||||
String JOB_LOG_STATUS = "infra_job_log_status"; // 定时任务日志状态的枚举
|
||||
|
||||
String API_ERROR_LOG_PROCESS_STATUS = "infra_api_error_log_process_status"; // API 错误日志的处理状态的枚举
|
||||
|
||||
String CONFIG_TYPE = "infra_config_type"; // 参数配置类型
|
||||
String BOOLEAN_STRING = "infra_boolean_string"; // Boolean 是否类型
|
||||
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package cn.iocoder.yudao.module.infra.enums;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
|
||||
/**
|
||||
* Infra 错误码枚举类
|
||||
*
|
||||
* infra 系统,使用 1-001-000-000 段
|
||||
*/
|
||||
public interface ErrorCodeConstants {
|
||||
|
||||
// ========== 参数配置 1-001-000-000 ==========
|
||||
ErrorCode CONFIG_NOT_EXISTS = new ErrorCode(1_001_000_001, "参数配置不存在");
|
||||
ErrorCode CONFIG_KEY_DUPLICATE = new ErrorCode(1_001_000_002, "参数配置 key 重复");
|
||||
ErrorCode CONFIG_CAN_NOT_DELETE_SYSTEM_TYPE = new ErrorCode(1_001_000_003, "不能删除类型为系统内置的参数配置");
|
||||
ErrorCode CONFIG_GET_VALUE_ERROR_IF_VISIBLE = new ErrorCode(1_001_000_004, "获取参数配置失败,原因:不允许获取不可见配置");
|
||||
|
||||
// ========== 定时任务 1-001-001-000 ==========
|
||||
ErrorCode JOB_NOT_EXISTS = new ErrorCode(1_001_001_000, "定时任务不存在");
|
||||
ErrorCode JOB_HANDLER_EXISTS = new ErrorCode(1_001_001_001, "定时任务的处理器已经存在");
|
||||
ErrorCode JOB_CHANGE_STATUS_INVALID = new ErrorCode(1_001_001_002, "只允许修改为开启或者关闭状态");
|
||||
ErrorCode JOB_CHANGE_STATUS_EQUALS = new ErrorCode(1_001_001_003, "定时任务已经处于该状态,无需修改");
|
||||
ErrorCode JOB_UPDATE_ONLY_NORMAL_STATUS = new ErrorCode(1_001_001_004, "只有开启状态的任务,才可以修改");
|
||||
ErrorCode JOB_CRON_EXPRESSION_VALID = new ErrorCode(1_001_001_005, "CRON 表达式不正确");
|
||||
|
||||
// ========== API 错误日志 1-001-002-000 ==========
|
||||
ErrorCode API_ERROR_LOG_NOT_FOUND = new ErrorCode(1_001_002_000, "API 错误日志不存在");
|
||||
ErrorCode API_ERROR_LOG_PROCESSED = new ErrorCode(1_001_002_001, "API 错误日志已处理");
|
||||
|
||||
// ========= 文件相关 1-001-003-000 =================
|
||||
ErrorCode FILE_PATH_EXISTS = new ErrorCode(1_001_003_000, "文件路径已存在");
|
||||
ErrorCode FILE_NOT_EXISTS = new ErrorCode(1_001_003_001, "文件不存在");
|
||||
ErrorCode FILE_IS_EMPTY = new ErrorCode(1_001_003_002, "文件为空");
|
||||
|
||||
// ========== 代码生成器 1-001-004-000 ==========
|
||||
ErrorCode CODEGEN_TABLE_EXISTS = new ErrorCode(1_001_004_002, "表定义已经存在");
|
||||
ErrorCode CODEGEN_IMPORT_TABLE_NULL = new ErrorCode(1_001_004_001, "导入的表不存在");
|
||||
ErrorCode CODEGEN_IMPORT_COLUMNS_NULL = new ErrorCode(1_001_004_002, "导入的字段不存在");
|
||||
ErrorCode CODEGEN_TABLE_NOT_EXISTS = new ErrorCode(1_001_004_004, "表定义不存在");
|
||||
ErrorCode CODEGEN_COLUMN_NOT_EXISTS = new ErrorCode(1_001_004_005, "字段义不存在");
|
||||
ErrorCode CODEGEN_SYNC_COLUMNS_NULL = new ErrorCode(1_001_004_006, "同步的字段不存在");
|
||||
ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1_001_004_007, "同步失败,不存在改变");
|
||||
ErrorCode CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL = new ErrorCode(1_001_004_008, "数据库的表注释未填写");
|
||||
ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1_001_004_009, "数据库的表字段({})注释未填写");
|
||||
ErrorCode CODEGEN_MASTER_TABLE_NOT_EXISTS = new ErrorCode(1_001_004_010, "主表(id={})定义不存在,请检查");
|
||||
ErrorCode CODEGEN_SUB_COLUMN_NOT_EXISTS = new ErrorCode(1_001_004_011, "子表的字段(id={})不存在,请检查");
|
||||
ErrorCode CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_TABLE = new ErrorCode(1_001_004_012, "主表生成代码失败,原因:它没有子表");
|
||||
ErrorCode CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_COLUMN = new ErrorCode(1_001_004_013, "主表生成代码失败,原因:它的子表({})没有字段");
|
||||
|
||||
// ========== 文件配置 1-001-006-000 ==========
|
||||
ErrorCode FILE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_006_000, "文件配置不存在");
|
||||
ErrorCode FILE_CONFIG_DELETE_FAIL_MASTER = new ErrorCode(1_001_006_001, "该文件配置不允许删除,原因:它是主配置,删除会导致无法上传文件");
|
||||
|
||||
// ========== 数据源配置 1-001-007-000 ==========
|
||||
ErrorCode DATA_SOURCE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_007_000, "数据源配置不存在");
|
||||
ErrorCode DATA_SOURCE_CONFIG_NOT_OK = new ErrorCode(1_001_007_001, "数据源配置不正确,无法进行连接");
|
||||
|
||||
// ========== 数据源配置 1-001-107-000 ==========
|
||||
ErrorCode DEMO_STUDENT_NOT_EXISTS = new ErrorCode(1_001_107_000, "学生不存在");
|
||||
|
||||
// ========== 学生 1-001-201-000 ==========
|
||||
ErrorCode DEMO01_CONTACT_NOT_EXISTS = new ErrorCode(1_001_201_000, "示例联系人不存在");
|
||||
ErrorCode DEMO02_CATEGORY_NOT_EXISTS = new ErrorCode(1_001_201_001, "示例分类不存在");
|
||||
ErrorCode DEMO02_CATEGORY_EXITS_CHILDREN = new ErrorCode(1_001_201_002, "存在存在子示例分类,无法删除");
|
||||
ErrorCode DEMO02_CATEGORY_PARENT_NOT_EXITS = new ErrorCode(1_001_201_003,"父级示例分类不存在");
|
||||
ErrorCode DEMO02_CATEGORY_PARENT_ERROR = new ErrorCode(1_001_201_004, "不能设置自己为父示例分类");
|
||||
ErrorCode DEMO02_CATEGORY_NAME_DUPLICATE = new ErrorCode(1_001_201_005, "已经存在该名字的示例分类");
|
||||
ErrorCode DEMO02_CATEGORY_PARENT_IS_CHILD = new ErrorCode(1_001_201_006, "不能设置自己的子示例分类为父示例分类");
|
||||
ErrorCode DEMO03_STUDENT_NOT_EXISTS = new ErrorCode(1_001_201_007, "学生不存在");
|
||||
ErrorCode DEMO03_GRADE_NOT_EXISTS = new ErrorCode(1_001_201_008, "学生班级不存在");
|
||||
ErrorCode DEMO03_GRADE_EXISTS = new ErrorCode(1_001_201_009, "学生班级已存在");
|
||||
|
||||
}
|
139
yudao-module-infra/yudao-module-infra-biz/pom.xml
Normal file
139
yudao-module-infra/yudao-module-infra-biz/pom.xml
Normal file
@ -0,0 +1,139 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-infra</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>yudao-module-infra-biz</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
infra 模块,主要提供两块能力:
|
||||
1. 我们放基础设施的运维与管理,支撑上层的通用与核心业务。 例如说:定时任务的管理、服务器的信息等等
|
||||
2. 研发工具,提升研发效率与质量。 例如说:代码生成器、接口文档等等
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-system-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-infra-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 业务组件 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- DB 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-generator</artifactId> <!-- 代码生成器,使用它解析表结构 -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Config 配置中心相关 -->
|
||||
|
||||
<!-- Job 定时任务相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-job</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 消息队列相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-mq</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test 测试相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-excel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity-engine-core</artifactId> <!-- 实现代码生成 -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.smallbun.screw</groupId>
|
||||
<artifactId>screw-core</artifactId> <!-- 实现数据库文档 -->
|
||||
</dependency>
|
||||
|
||||
<!-- 监控相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-monitor</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-server</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 -->
|
||||
</dependency>
|
||||
|
||||
<!-- 三方云服务相关 -->
|
||||
<dependency>
|
||||
<groupId>commons-net</groupId>
|
||||
<artifactId>commons-net</artifactId> <!-- 文件客户端:解决 ftp 连接 -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jsch</artifactId> <!-- 文件客户端:解决 sftp 连接 -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId> <!-- 文件客户端:解决阿里云、腾讯云、minio 等 S3 连接 -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-core</artifactId> <!-- 文件客户端:文件类型的识别 -->
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.infra.api.file;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.service.file.FileService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 文件 API 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class FileApiImpl implements FileApi {
|
||||
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
|
||||
@Override
|
||||
public String createFile(String name, String path, byte[] content) {
|
||||
return fileService.createFile(name, path, content);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package cn.iocoder.yudao.module.infra.api.logger;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.infra.service.logger.ApiAccessLogService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* API 访问日志的 API 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class ApiAccessLogApiImpl implements ApiAccessLogApi {
|
||||
|
||||
@Resource
|
||||
private ApiAccessLogService apiAccessLogService;
|
||||
|
||||
@Override
|
||||
public void createApiAccessLog(ApiAccessLogCreateReqDTO createDTO) {
|
||||
apiAccessLogService.createApiAccessLog(createDTO);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package cn.iocoder.yudao.module.infra.api.logger;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.infra.service.logger.ApiErrorLogService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* API 访问日志的 API 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class ApiErrorLogApiImpl implements ApiErrorLogApi {
|
||||
|
||||
@Resource
|
||||
private ApiErrorLogService apiErrorLogService;
|
||||
|
||||
@Override
|
||||
public void createApiErrorLog(ApiErrorLogCreateReqDTO createDTO) {
|
||||
apiErrorLogService.createApiErrorLog(createDTO);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
package cn.iocoder.yudao.module.infra.api;
|
@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.infra.api.websocket;
|
||||
|
||||
import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* WebSocket 发送器的 API 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Component
|
||||
public class WebSocketSenderApiImpl implements WebSocketSenderApi {
|
||||
|
||||
@Resource
|
||||
private WebSocketMessageSender webSocketMessageSender;
|
||||
|
||||
@Override
|
||||
public void send(Integer userType, Long userId, String messageType, String messageContent) {
|
||||
webSocketMessageSender.send(userType, userId, messageType, messageContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Integer userType, String messageType, String messageContent) {
|
||||
webSocketMessageSender.send(userType, messageType, messageContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(String sessionId, String messageType, String messageContent) {
|
||||
webSocketMessageSender.send(sessionId, messageType, messageContent);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenCreateListReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenDetailRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenPreviewRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTableRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.DatabaseTableRespVO;
|
||||
import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
import cn.iocoder.yudao.module.infra.service.codegen.CodegenService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "管理后台 - 代码生成器")
|
||||
@RestController
|
||||
@RequestMapping("/infra/codegen")
|
||||
@Validated
|
||||
public class CodegenController {
|
||||
|
||||
@Resource
|
||||
private CodegenService codegenService;
|
||||
|
||||
@GetMapping("/db/table/list")
|
||||
@Operation(summary = "获得数据库自带的表定义列表", description = "会过滤掉已经导入 Codegen 的表")
|
||||
@Parameters({
|
||||
@Parameter(name = "dataSourceConfigId", description = "数据源配置的编号", required = true, example = "1"),
|
||||
@Parameter(name = "name", description = "表名,模糊匹配", example = "yudao"),
|
||||
@Parameter(name = "comment", description = "描述,模糊匹配", example = "芋道")
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:query')")
|
||||
public CommonResult<List<DatabaseTableRespVO>> getDatabaseTableList(
|
||||
@RequestParam(value = "dataSourceConfigId") Long dataSourceConfigId,
|
||||
@RequestParam(value = "name", required = false) String name,
|
||||
@RequestParam(value = "comment", required = false) String comment) {
|
||||
return success(codegenService.getDatabaseTableList(dataSourceConfigId, name, comment));
|
||||
}
|
||||
|
||||
@GetMapping("/table/list")
|
||||
@Operation(summary = "获得表定义列表")
|
||||
@Parameter(name = "dataSourceConfigId", description = "数据源配置的编号", required = true, example = "1")
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:query')")
|
||||
public CommonResult<List<CodegenTableRespVO>> getCodegenTableList(@RequestParam(value = "dataSourceConfigId") Long dataSourceConfigId) {
|
||||
List<CodegenTableDO> list = codegenService.getCodegenTableList(dataSourceConfigId);
|
||||
return success(BeanUtils.toBean(list, CodegenTableRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/table/page")
|
||||
@Operation(summary = "获得表定义分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:query')")
|
||||
public CommonResult<PageResult<CodegenTableRespVO>> getCodegenTablePage(@Valid CodegenTablePageReqVO pageReqVO) {
|
||||
PageResult<CodegenTableDO> pageResult = codegenService.getCodegenTablePage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, CodegenTableRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/detail")
|
||||
@Operation(summary = "获得表和字段的明细")
|
||||
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:query')")
|
||||
public CommonResult<CodegenDetailRespVO> getCodegenDetail(@RequestParam("tableId") Long tableId) {
|
||||
CodegenTableDO table = codegenService.getCodegenTable(tableId);
|
||||
List<CodegenColumnDO> columns = codegenService.getCodegenColumnListByTableId(tableId);
|
||||
// 拼装返回
|
||||
return success(CodegenConvert.INSTANCE.convert(table, columns));
|
||||
}
|
||||
|
||||
@Operation(summary = "基于数据库的表结构,创建代码生成器的表和字段定义")
|
||||
@PostMapping("/create-list")
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:create')")
|
||||
public CommonResult<List<Long>> createCodegenList(@Valid @RequestBody CodegenCreateListReqVO reqVO) {
|
||||
return success(codegenService.createCodegenList(getLoginUserId(), reqVO));
|
||||
}
|
||||
|
||||
@Operation(summary = "更新数据库的表和字段定义")
|
||||
@PutMapping("/update")
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:update')")
|
||||
public CommonResult<Boolean> updateCodegen(@Valid @RequestBody CodegenUpdateReqVO updateReqVO) {
|
||||
codegenService.updateCodegen(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Operation(summary = "基于数据库的表结构,同步数据库的表和字段定义")
|
||||
@PutMapping("/sync-from-db")
|
||||
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:update')")
|
||||
public CommonResult<Boolean> syncCodegenFromDB(@RequestParam("tableId") Long tableId) {
|
||||
codegenService.syncCodegenFromDB(tableId);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Operation(summary = "删除数据库的表和字段定义")
|
||||
@DeleteMapping("/delete")
|
||||
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:delete')")
|
||||
public CommonResult<Boolean> deleteCodegen(@RequestParam("tableId") Long tableId) {
|
||||
codegenService.deleteCodegen(tableId);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Operation(summary = "预览生成代码")
|
||||
@GetMapping("/preview")
|
||||
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:preview')")
|
||||
public CommonResult<List<CodegenPreviewRespVO>> previewCodegen(@RequestParam("tableId") Long tableId) {
|
||||
Map<String, String> codes = codegenService.generationCodes(tableId);
|
||||
return success(CodegenConvert.INSTANCE.convert(codes));
|
||||
}
|
||||
|
||||
@Operation(summary = "下载生成代码")
|
||||
@GetMapping("/download")
|
||||
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:download')")
|
||||
public void downloadCodegen(@RequestParam("tableId") Long tableId,
|
||||
HttpServletResponse response) throws IOException {
|
||||
// 生成代码
|
||||
Map<String, String> codes = codegenService.generationCodes(tableId);
|
||||
// 构建 zip 包
|
||||
String[] paths = codes.keySet().toArray(new String[0]);
|
||||
ByteArrayInputStream[] ins = codes.values().stream().map(IoUtil::toUtf8Stream).toArray(ByteArrayInputStream[]::new);
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
ZipUtil.zip(outputStream, paths, ins);
|
||||
// 输出
|
||||
ServletUtils.writeAttachment(response, "codegen.zip", outputStream.toByteArray());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 基于数据库的表结构,创建代码生成器的表和字段定义 Request VO")
|
||||
@Data
|
||||
public class CodegenCreateListReqVO {
|
||||
|
||||
@Schema(description = "数据源配置的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "数据源配置的编号不能为空")
|
||||
private Long dataSourceConfigId;
|
||||
|
||||
@Schema(description = "表名数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2, 3]")
|
||||
@NotNull(message = "表名数组不能为空")
|
||||
private List<String> tableNames;
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.column.CodegenColumnRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTableRespVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 代码生成表和字段的明细 Response VO")
|
||||
@Data
|
||||
public class CodegenDetailRespVO {
|
||||
|
||||
@Schema(description = "表定义")
|
||||
private CodegenTableRespVO table;
|
||||
|
||||
@Schema(description = "字段定义")
|
||||
private List<CodegenColumnRespVO> columns;
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 代码生成预览 Response VO,注意,每个文件都是一个该对象")
|
||||
@Data
|
||||
public class CodegenPreviewRespVO {
|
||||
|
||||
@Schema(description = "文件路径", requiredMode = Schema.RequiredMode.REQUIRED, example = "java/cn/iocoder/yudao/adminserver/modules/system/controller/test/SysTestDemoController.java")
|
||||
private String filePath;
|
||||
|
||||
@Schema(description = "代码", requiredMode = Schema.RequiredMode.REQUIRED, example = "Hello World")
|
||||
private String code;
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.column.CodegenColumnSaveReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTableSaveReqVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 代码生成表和字段的修改 Request VO")
|
||||
@Data
|
||||
public class CodegenUpdateReqVO {
|
||||
|
||||
@Valid // 校验内嵌的字段
|
||||
@NotNull(message = "表定义不能为空")
|
||||
private CodegenTableSaveReqVO table;
|
||||
|
||||
@Valid // 校验内嵌的字段
|
||||
@NotNull(message = "字段定义不能为空")
|
||||
private List<CodegenColumnSaveReqVO> columns;
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.column;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 代码生成字段定义 Response VO")
|
||||
@Data
|
||||
public class CodegenColumnRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "表编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long tableId;
|
||||
|
||||
@Schema(description = "字段名", requiredMode = Schema.RequiredMode.REQUIRED, example = "user_age")
|
||||
private String columnName;
|
||||
|
||||
@Schema(description = "字段类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "int(11)")
|
||||
private String dataType;
|
||||
|
||||
@Schema(description = "字段描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "年龄")
|
||||
private String columnComment;
|
||||
|
||||
@Schema(description = "是否允许为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
private Boolean nullable;
|
||||
|
||||
@Schema(description = "是否主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
|
||||
private Boolean primaryKey;
|
||||
|
||||
@Schema(description = "是否自增", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
private Boolean autoIncrement;
|
||||
|
||||
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
private Integer ordinalPosition;
|
||||
|
||||
@Schema(description = "Java 属性类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "userAge")
|
||||
private String javaType;
|
||||
|
||||
@Schema(description = "Java 属性名", requiredMode = Schema.RequiredMode.REQUIRED, example = "Integer")
|
||||
private String javaField;
|
||||
|
||||
@Schema(description = "字典类型", example = "sys_gender")
|
||||
private String dictType;
|
||||
|
||||
@Schema(description = "数据示例", example = "1024")
|
||||
private String example;
|
||||
|
||||
@Schema(description = "是否为 Create 创建操作的字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
private Boolean createOperation;
|
||||
|
||||
@Schema(description = "是否为 Update 更新操作的字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
|
||||
private Boolean updateOperation;
|
||||
|
||||
@Schema(description = "是否为 List 查询操作的字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
private Boolean listOperation;
|
||||
|
||||
@Schema(description = "List 查询操作的条件类型,参见 CodegenColumnListConditionEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "LIKE")
|
||||
private String listOperationCondition;
|
||||
|
||||
@Schema(description = "是否为 List 查询操作的返回字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
private Boolean listOperationResult;
|
||||
|
||||
@Schema(description = "显示类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "input")
|
||||
private String htmlType;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.column;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 代码生成字段定义创建/修改 Request VO")
|
||||
@Data
|
||||
public class CodegenColumnSaveReqVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "表编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "表编号不能为空")
|
||||
private Long tableId;
|
||||
|
||||
@Schema(description = "字段名", requiredMode = Schema.RequiredMode.REQUIRED, example = "user_age")
|
||||
@NotNull(message = "字段名不能为空")
|
||||
private String columnName;
|
||||
|
||||
@Schema(description = "字段类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "int(11)")
|
||||
@NotNull(message = "字段类型不能为空")
|
||||
private String dataType;
|
||||
|
||||
@Schema(description = "字段描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "年龄")
|
||||
@NotNull(message = "字段描述不能为空")
|
||||
private String columnComment;
|
||||
|
||||
@Schema(description = "是否允许为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@NotNull(message = "是否允许为空不能为空")
|
||||
private Boolean nullable;
|
||||
|
||||
@Schema(description = "是否主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
|
||||
@NotNull(message = "是否主键不能为空")
|
||||
private Boolean primaryKey;
|
||||
|
||||
@Schema(description = "是否自增", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@NotNull(message = "是否自增不能为空")
|
||||
private Boolean autoIncrement;
|
||||
|
||||
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
@NotNull(message = "排序不能为空")
|
||||
private Integer ordinalPosition;
|
||||
|
||||
@Schema(description = "Java 属性类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "userAge")
|
||||
@NotNull(message = "Java 属性类型不能为空")
|
||||
private String javaType;
|
||||
|
||||
@Schema(description = "Java 属性名", requiredMode = Schema.RequiredMode.REQUIRED, example = "Integer")
|
||||
@NotNull(message = "Java 属性名不能为空")
|
||||
private String javaField;
|
||||
|
||||
@Schema(description = "字典类型", example = "sys_gender")
|
||||
private String dictType;
|
||||
|
||||
@Schema(description = "数据示例", example = "1024")
|
||||
private String example;
|
||||
|
||||
@Schema(description = "是否为 Create 创建操作的字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@NotNull(message = "是否为 Create 创建操作的字段不能为空")
|
||||
private Boolean createOperation;
|
||||
|
||||
@Schema(description = "是否为 Update 更新操作的字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
|
||||
@NotNull(message = "是否为 Update 更新操作的字段不能为空")
|
||||
private Boolean updateOperation;
|
||||
|
||||
@Schema(description = "是否为 List 查询操作的字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@NotNull(message = "是否为 List 查询操作的字段不能为空")
|
||||
private Boolean listOperation;
|
||||
|
||||
@Schema(description = "List 查询操作的条件类型,参见 CodegenColumnListConditionEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "LIKE")
|
||||
@NotNull(message = "List 查询操作的条件类型不能为空")
|
||||
private String listOperationCondition;
|
||||
|
||||
@Schema(description = "是否为 List 查询操作的返回字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@NotNull(message = "是否为 List 查询操作的返回字段不能为空")
|
||||
private Boolean listOperationResult;
|
||||
|
||||
@Schema(description = "显示类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "input")
|
||||
@NotNull(message = "显示类型不能为空")
|
||||
private String htmlType;
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 表定义分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class CodegenTablePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "表名称,模糊匹配", example = "yudao")
|
||||
private String tableName;
|
||||
|
||||
@Schema(description = "表描述,模糊匹配", example = "芋道")
|
||||
private String tableComment;
|
||||
|
||||
@Schema(description = "实体,模糊匹配", example = "Yudao")
|
||||
private String className;
|
||||
|
||||
@Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 代码生成表定义 Response VO")
|
||||
@Data
|
||||
public class CodegenTableRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "生成场景,参见 CodegenSceneEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer scene;
|
||||
|
||||
@Schema(description = "表名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
|
||||
private String tableName;
|
||||
|
||||
@Schema(description = "表描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
|
||||
private String tableComment;
|
||||
|
||||
@Schema(description = "备注", example = "我是备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "模块名", requiredMode = Schema.RequiredMode.REQUIRED, example = "system")
|
||||
private String moduleName;
|
||||
|
||||
@Schema(description = "业务名", requiredMode = Schema.RequiredMode.REQUIRED, example = "codegen")
|
||||
private String businessName;
|
||||
|
||||
@Schema(description = "类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "CodegenTable")
|
||||
private String className;
|
||||
|
||||
@Schema(description = "类描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "代码生成器的表定义")
|
||||
private String classComment;
|
||||
|
||||
@Schema(description = "作者", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
|
||||
private String author;
|
||||
|
||||
@Schema(description = "模板类型,参见 CodegenTemplateTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer templateType;
|
||||
|
||||
@Schema(description = "前端类型,参见 CodegenFrontTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
|
||||
private Integer frontType;
|
||||
|
||||
@Schema(description = "父菜单编号", example = "1024")
|
||||
private Long parentMenuId;
|
||||
|
||||
@Schema(description = "主表的编号", example = "2048")
|
||||
private Long masterTableId;
|
||||
@Schema(description = "子表关联主表的字段编号", example = "4096")
|
||||
private Long subJoinColumnId;
|
||||
@Schema(description = "主表与子表是否一对多", example = "4096")
|
||||
private Boolean subJoinMany;
|
||||
|
||||
@Schema(description = "树表的父字段编号", example = "8192")
|
||||
private Long treeParentColumnId;
|
||||
@Schema(description = "树表的名字字段编号", example = "16384")
|
||||
private Long treeNameColumnId;
|
||||
|
||||
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer dataSourceConfigId;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.AssertTrue;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 代码生成表定义创建/修改 Response VO")
|
||||
@Data
|
||||
public class CodegenTableSaveReqVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "生成场景,参见 CodegenSceneEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "导入类型不能为空")
|
||||
private Integer scene;
|
||||
|
||||
@Schema(description = "表名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
|
||||
@NotNull(message = "表名称不能为空")
|
||||
private String tableName;
|
||||
|
||||
@Schema(description = "表描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
|
||||
@NotNull(message = "表描述不能为空")
|
||||
private String tableComment;
|
||||
|
||||
@Schema(description = "备注", example = "我是备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "模块名", requiredMode = Schema.RequiredMode.REQUIRED, example = "system")
|
||||
@NotNull(message = "模块名不能为空")
|
||||
private String moduleName;
|
||||
|
||||
@Schema(description = "业务名", requiredMode = Schema.RequiredMode.REQUIRED, example = "codegen")
|
||||
@NotNull(message = "业务名不能为空")
|
||||
private String businessName;
|
||||
|
||||
@Schema(description = "类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "CodegenTable")
|
||||
@NotNull(message = "类名称不能为空")
|
||||
private String className;
|
||||
|
||||
@Schema(description = "类描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "代码生成器的表定义")
|
||||
@NotNull(message = "类描述不能为空")
|
||||
private String classComment;
|
||||
|
||||
@Schema(description = "作者", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
|
||||
@NotNull(message = "作者不能为空")
|
||||
private String author;
|
||||
|
||||
@Schema(description = "模板类型,参见 CodegenTemplateTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "模板类型不能为空")
|
||||
private Integer templateType;
|
||||
|
||||
@Schema(description = "前端类型,参见 CodegenFrontTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
|
||||
@NotNull(message = "前端类型不能为空")
|
||||
private Integer frontType;
|
||||
|
||||
@Schema(description = "父菜单编号", example = "1024")
|
||||
private Long parentMenuId;
|
||||
|
||||
@Schema(description = "主表的编号", example = "2048")
|
||||
private Long masterTableId;
|
||||
@Schema(description = "子表关联主表的字段编号", example = "4096")
|
||||
private Long subJoinColumnId;
|
||||
@Schema(description = "主表与子表是否一对多", example = "4096")
|
||||
private Boolean subJoinMany;
|
||||
|
||||
@Schema(description = "树表的父字段编号", example = "8192")
|
||||
private Long treeParentColumnId;
|
||||
@Schema(description = "树表的名字字段编号", example = "16384")
|
||||
private Long treeNameColumnId;
|
||||
|
||||
@AssertTrue(message = "上级菜单不能为空,请前往 [修改生成配置 -> 生成信息] 界面,设置“上级菜单”字段")
|
||||
@JsonIgnore
|
||||
public boolean isParentMenuIdValid() {
|
||||
// 生成场景为管理后台时,必须设置上级菜单,不然生成的菜单 SQL 是无父级菜单的
|
||||
return ObjectUtil.notEqual(getScene(), CodegenSceneEnum.ADMIN.getScene())
|
||||
|| getParentMenuId() != null;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "关联的父表信息不全")
|
||||
@JsonIgnore
|
||||
public boolean isSubValid() {
|
||||
return ObjectUtil.notEqual(getTemplateType(), CodegenTemplateTypeEnum.SUB)
|
||||
|| (ObjectUtil.isAllNotEmpty(masterTableId, subJoinColumnId, subJoinMany));
|
||||
}
|
||||
|
||||
@AssertTrue(message = "关联的树表信息不全")
|
||||
@JsonIgnore
|
||||
public boolean isTreeValid() {
|
||||
return ObjectUtil.notEqual(templateType, CodegenTemplateTypeEnum.TREE)
|
||||
|| (ObjectUtil.isAllNotEmpty(treeParentColumnId, treeNameColumnId));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 数据库的表定义 Response VO")
|
||||
@Data
|
||||
public class DatabaseTableRespVO {
|
||||
|
||||
@Schema(description = "表名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "yuanma")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "表描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
|
||||
private String comment;
|
||||
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.config.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.convert.config.ConfigConvert;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO;
|
||||
import cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants;
|
||||
import cn.iocoder.yudao.module.infra.service.config.ConfigService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Tag(name = "管理后台 - 参数配置")
|
||||
@RestController
|
||||
@RequestMapping("/infra/config")
|
||||
@Validated
|
||||
public class ConfigController {
|
||||
|
||||
@Resource
|
||||
private ConfigService configService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建参数配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:config:create')")
|
||||
public CommonResult<Long> createConfig(@Valid @RequestBody ConfigSaveReqVO createReqVO) {
|
||||
return success(configService.createConfig(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "修改参数配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:config:update')")
|
||||
public CommonResult<Boolean> updateConfig(@Valid @RequestBody ConfigSaveReqVO updateReqVO) {
|
||||
configService.updateConfig(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除参数配置")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:config:delete')")
|
||||
public CommonResult<Boolean> deleteConfig(@RequestParam("id") Long id) {
|
||||
configService.deleteConfig(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/get")
|
||||
@Operation(summary = "获得参数配置")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:config:query')")
|
||||
public CommonResult<ConfigRespVO> getConfig(@RequestParam("id") Long id) {
|
||||
return success(ConfigConvert.INSTANCE.convert(configService.getConfig(id)));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/get-value-by-key")
|
||||
@Operation(summary = "根据参数键名查询参数值", description = "不可见的配置,不允许返回给前端")
|
||||
@Parameter(name = "key", description = "参数键", required = true, example = "yunai.biz.username")
|
||||
public CommonResult<String> getConfigKey(@RequestParam("key") String key) {
|
||||
ConfigDO config = configService.getConfigByKey(key);
|
||||
if (config == null) {
|
||||
return success(null);
|
||||
}
|
||||
if (!config.getVisible()) {
|
||||
throw exception(ErrorCodeConstants.CONFIG_GET_VALUE_ERROR_IF_VISIBLE);
|
||||
}
|
||||
return success(config.getValue());
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获取参数配置分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:config:query')")
|
||||
public CommonResult<PageResult<ConfigRespVO>> getConfigPage(@Valid ConfigPageReqVO pageReqVO) {
|
||||
PageResult<ConfigDO> page = configService.getConfigPage(pageReqVO);
|
||||
return success(ConfigConvert.INSTANCE.convertPage(page));
|
||||
}
|
||||
|
||||
@GetMapping("/export")
|
||||
@Operation(summary = "导出参数配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:config:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportConfig(@Valid ConfigPageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<ConfigDO> list = configService.getConfigPage(exportReqVO).getList();
|
||||
// 输出
|
||||
ExcelUtils.write(response, "参数配置.xls", "数据", ConfigRespVO.class,
|
||||
ConfigConvert.INSTANCE.convertList(list));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.config.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 参数配置分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class ConfigPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "数据源名称,模糊匹配", example = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "参数键名,模糊匹配", example = "yunai.db.username")
|
||||
private String key;
|
||||
|
||||
@Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", example = "1")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.config.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||
import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 参数配置信息 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class ConfigRespVO {
|
||||
|
||||
@Schema(description = "参数配置序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@ExcelProperty("参数配置序号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "参数分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "biz")
|
||||
@ExcelProperty("参数分类")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "参数名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "数据库名")
|
||||
@ExcelProperty("参数名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "参数键名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yunai.db.username")
|
||||
@ExcelProperty("参数键名")
|
||||
private String key;
|
||||
|
||||
@Schema(description = "参数键值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@ExcelProperty("参数键值")
|
||||
private String value;
|
||||
|
||||
@Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty(value = "参数类型", converter = DictConvert.class)
|
||||
@DictFormat(DictTypeConstants.CONFIG_TYPE)
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@ExcelProperty(value = "是否可见", converter = DictConvert.class)
|
||||
@DictFormat(DictTypeConstants.BOOLEAN_STRING)
|
||||
private Boolean visible;
|
||||
|
||||
@Schema(description = "备注", example = "备注一下很帅气!")
|
||||
@ExcelProperty("备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.config.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
@Schema(description = "管理后台 - 参数配置创建/修改 Request VO")
|
||||
@Data
|
||||
public class ConfigSaveReqVO {
|
||||
|
||||
@Schema(description = "参数配置序号", example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "参数分组", requiredMode = Schema.RequiredMode.REQUIRED, example = "biz")
|
||||
@NotEmpty(message = "参数分组不能为空")
|
||||
@Size(max = 50, message = "参数名称不能超过 50 个字符")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "参数名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "数据库名")
|
||||
@NotBlank(message = "参数名称不能为空")
|
||||
@Size(max = 100, message = "参数名称不能超过 100 个字符")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "参数键名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yunai.db.username")
|
||||
@NotBlank(message = "参数键名长度不能为空")
|
||||
@Size(max = 100, message = "参数键名长度不能超过 100 个字符")
|
||||
private String key;
|
||||
|
||||
@Schema(description = "参数键值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotBlank(message = "参数键值不能为空")
|
||||
@Size(max = 500, message = "参数键值长度不能超过 500 个字符")
|
||||
private String value;
|
||||
|
||||
@Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@NotNull(message = "是否可见不能为空")
|
||||
private Boolean visible;
|
||||
|
||||
@Schema(description = "备注", example = "备注一下很帅气!")
|
||||
private String remark;
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.db;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigSaveReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
|
||||
import cn.iocoder.yudao.module.infra.service.db.DataSourceConfigService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 数据源配置")
|
||||
@RestController
|
||||
@RequestMapping("/infra/data-source-config")
|
||||
@Validated
|
||||
public class DataSourceConfigController {
|
||||
|
||||
@Resource
|
||||
private DataSourceConfigService dataSourceConfigService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建数据源配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:data-source-config:create')")
|
||||
public CommonResult<Long> createDataSourceConfig(@Valid @RequestBody DataSourceConfigSaveReqVO createReqVO) {
|
||||
return success(dataSourceConfigService.createDataSourceConfig(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新数据源配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:data-source-config:update')")
|
||||
public CommonResult<Boolean> updateDataSourceConfig(@Valid @RequestBody DataSourceConfigSaveReqVO updateReqVO) {
|
||||
dataSourceConfigService.updateDataSourceConfig(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除数据源配置")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:data-source-config:delete')")
|
||||
public CommonResult<Boolean> deleteDataSourceConfig(@RequestParam("id") Long id) {
|
||||
dataSourceConfigService.deleteDataSourceConfig(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得数据源配置")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:data-source-config:query')")
|
||||
public CommonResult<DataSourceConfigRespVO> getDataSourceConfig(@RequestParam("id") Long id) {
|
||||
DataSourceConfigDO config = dataSourceConfigService.getDataSourceConfig(id);
|
||||
return success(BeanUtils.toBean(config, DataSourceConfigRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获得数据源配置列表")
|
||||
@PreAuthorize("@ss.hasPermission('infra:data-source-config:query')")
|
||||
public CommonResult<List<DataSourceConfigRespVO>> getDataSourceConfigList() {
|
||||
List<DataSourceConfigDO> list = dataSourceConfigService.getDataSourceConfigList();
|
||||
return success(BeanUtils.toBean(list, DataSourceConfigRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.db;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.smallbun.screw.core.Configuration;
|
||||
import cn.smallbun.screw.core.engine.EngineConfig;
|
||||
import cn.smallbun.screw.core.engine.EngineFileType;
|
||||
import cn.smallbun.screw.core.engine.EngineTemplateType;
|
||||
import cn.smallbun.screw.core.execute.DocumentationExecute;
|
||||
import cn.smallbun.screw.core.process.ProcessConfig;
|
||||
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Tag(name = "管理后台 - 数据库文档")
|
||||
@RestController
|
||||
@RequestMapping("/infra/db-doc")
|
||||
public class DatabaseDocController {
|
||||
|
||||
@Resource
|
||||
private DynamicDataSourceProperties dynamicDataSourceProperties;
|
||||
|
||||
private static final String FILE_OUTPUT_DIR = System.getProperty("java.io.tmpdir") + File.separator
|
||||
+ "db-doc";
|
||||
private static final String DOC_FILE_NAME = "数据库文档";
|
||||
private static final String DOC_VERSION = "1.0.0";
|
||||
private static final String DOC_DESCRIPTION = "文档描述";
|
||||
|
||||
@GetMapping("/export-html")
|
||||
@Operation(summary = "导出 html 格式的数据文档")
|
||||
@Parameter(name = "deleteFile", description = "是否删除在服务器本地生成的数据库文档", example = "true")
|
||||
public void exportHtml(@RequestParam(defaultValue = "true") Boolean deleteFile,
|
||||
HttpServletResponse response) throws IOException {
|
||||
doExportFile(EngineFileType.HTML, deleteFile, response);
|
||||
}
|
||||
|
||||
@GetMapping("/export-word")
|
||||
@Operation(summary = "导出 word 格式的数据文档")
|
||||
@Parameter(name = "deleteFile", description = "是否删除在服务器本地生成的数据库文档", example = "true")
|
||||
public void exportWord(@RequestParam(defaultValue = "true") Boolean deleteFile,
|
||||
HttpServletResponse response) throws IOException {
|
||||
doExportFile(EngineFileType.WORD, deleteFile, response);
|
||||
}
|
||||
|
||||
@GetMapping("/export-markdown")
|
||||
@Operation(summary = "导出 markdown 格式的数据文档")
|
||||
@Parameter(name = "deleteFile", description = "是否删除在服务器本地生成的数据库文档", example = "true")
|
||||
public void exportMarkdown(@RequestParam(defaultValue = "true") Boolean deleteFile,
|
||||
HttpServletResponse response) throws IOException {
|
||||
doExportFile(EngineFileType.MD, deleteFile, response);
|
||||
}
|
||||
|
||||
private void doExportFile(EngineFileType fileOutputType, Boolean deleteFile,
|
||||
HttpServletResponse response) throws IOException {
|
||||
String docFileName = DOC_FILE_NAME + "_" + IdUtil.fastSimpleUUID();
|
||||
String filePath = doExportFile(fileOutputType, docFileName);
|
||||
String downloadFileName = DOC_FILE_NAME + fileOutputType.getFileSuffix(); //下载后的文件名
|
||||
try {
|
||||
// 读取,返回
|
||||
ServletUtils.writeAttachment(response, downloadFileName, FileUtil.readBytes(filePath));
|
||||
} finally {
|
||||
handleDeleteFile(deleteFile, filePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出文件,返回文件路径
|
||||
*
|
||||
* @param fileOutputType 文件类型
|
||||
* @param fileName 文件名, 无需 ".docx" 等文件后缀
|
||||
* @return 生成的文件所在路径
|
||||
*/
|
||||
private String doExportFile(EngineFileType fileOutputType, String fileName) {
|
||||
try (HikariDataSource dataSource = buildDataSource()) {
|
||||
// 创建 screw 的配置
|
||||
Configuration config = Configuration.builder()
|
||||
.version(DOC_VERSION) // 版本
|
||||
.description(DOC_DESCRIPTION) // 描述
|
||||
.dataSource(dataSource) // 数据源
|
||||
.engineConfig(buildEngineConfig(fileOutputType, fileName)) // 引擎配置
|
||||
.produceConfig(buildProcessConfig()) // 处理配置
|
||||
.build();
|
||||
|
||||
// 执行 screw,生成数据库文档
|
||||
new DocumentationExecute(config).execute();
|
||||
|
||||
return FILE_OUTPUT_DIR + File.separator + fileName + fileOutputType.getFileSuffix();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDeleteFile(Boolean deleteFile, String filePath) {
|
||||
if (!deleteFile) {
|
||||
return;
|
||||
}
|
||||
FileUtil.del(filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建数据源
|
||||
*/
|
||||
// TODO 芋艿:screw 暂时不支持 druid,尴尬
|
||||
private HikariDataSource buildDataSource() {
|
||||
// 获得 DataSource 数据源,目前只支持首个
|
||||
String primary = dynamicDataSourceProperties.getPrimary();
|
||||
DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource().get(primary);
|
||||
// 创建 HikariConfig 配置类
|
||||
HikariConfig hikariConfig = new HikariConfig();
|
||||
hikariConfig.setJdbcUrl(dataSourceProperty.getUrl());
|
||||
hikariConfig.setUsername(dataSourceProperty.getUsername());
|
||||
hikariConfig.setPassword(dataSourceProperty.getPassword());
|
||||
hikariConfig.addDataSourceProperty("useInformationSchema", "true"); // 设置可以获取 tables remarks 信息
|
||||
// 创建数据源
|
||||
return new HikariDataSource(hikariConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 screw 的引擎配置
|
||||
*/
|
||||
private static EngineConfig buildEngineConfig(EngineFileType fileOutputType, String docFileName) {
|
||||
return EngineConfig.builder()
|
||||
.fileOutputDir(FILE_OUTPUT_DIR) // 生成文件路径
|
||||
.openOutputDir(false) // 打开目录
|
||||
.fileType(fileOutputType) // 文件类型
|
||||
.produceType(EngineTemplateType.velocity) // 文件类型
|
||||
.fileName(docFileName) // 自定义文件名称
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 screw 的处理配置,一般可忽略
|
||||
* 指定生成逻辑、当存在指定表、指定表前缀、指定表后缀时,将生成指定表,其余表不生成、并跳过忽略表配置
|
||||
*/
|
||||
private static ProcessConfig buildProcessConfig() {
|
||||
return ProcessConfig.builder()
|
||||
.ignoreTablePrefix(Arrays.asList("QRTZ_", "ACT_", "FLW_")) // 忽略表前缀
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.db.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 数据源配置 Response VO")
|
||||
@Data
|
||||
public class DataSourceConfigRespVO {
|
||||
|
||||
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "数据源名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "test")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "数据源连接", requiredMode = Schema.RequiredMode.REQUIRED, example = "jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "root")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.db.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
@Schema(description = "管理后台 - 数据源配置创建/修改 Request VO")
|
||||
@Data
|
||||
public class DataSourceConfigSaveReqVO {
|
||||
|
||||
@Schema(description = "主键编号", example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "数据源名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "test")
|
||||
@NotNull(message = "数据源名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "数据源连接", requiredMode = Schema.RequiredMode.REQUIRED, example = "jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro")
|
||||
@NotNull(message = "数据源连接不能为空")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "root")
|
||||
@NotNull(message = "用户名不能为空")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
|
||||
@NotNull(message = "密码不能为空")
|
||||
private String password;
|
||||
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactPageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactSaveReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo01.Demo01ContactDO;
|
||||
import cn.iocoder.yudao.module.infra.service.demo.demo01.Demo01ContactService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Tag(name = "管理后台 - 示例联系人")
|
||||
@RestController
|
||||
@RequestMapping("/infra/demo01-contact")
|
||||
@Validated
|
||||
public class Demo01ContactController {
|
||||
|
||||
@Resource
|
||||
private Demo01ContactService demo01ContactService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建示例联系人")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:create')")
|
||||
public CommonResult<Long> createDemo01Contact(@Valid @RequestBody Demo01ContactSaveReqVO createReqVO) {
|
||||
return success(demo01ContactService.createDemo01Contact(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新示例联系人")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:update')")
|
||||
public CommonResult<Boolean> updateDemo01Contact(@Valid @RequestBody Demo01ContactSaveReqVO updateReqVO) {
|
||||
demo01ContactService.updateDemo01Contact(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除示例联系人")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:delete')")
|
||||
public CommonResult<Boolean> deleteDemo01Contact(@RequestParam("id") Long id) {
|
||||
demo01ContactService.deleteDemo01Contact(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得示例联系人")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:query')")
|
||||
public CommonResult<Demo01ContactRespVO> getDemo01Contact(@RequestParam("id") Long id) {
|
||||
Demo01ContactDO demo01Contact = demo01ContactService.getDemo01Contact(id);
|
||||
return success(BeanUtils.toBean(demo01Contact, Demo01ContactRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得示例联系人分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:query')")
|
||||
public CommonResult<PageResult<Demo01ContactRespVO>> getDemo01ContactPage(@Valid Demo01ContactPageReqVO pageReqVO) {
|
||||
PageResult<Demo01ContactDO> pageResult = demo01ContactService.getDemo01ContactPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, Demo01ContactRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出示例联系人 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo01-contact:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportDemo01ContactExcel(@Valid Demo01ContactPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<Demo01ContactDO> list = demo01ContactService.getDemo01ContactPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "示例联系人.xls", "数据", Demo01ContactRespVO.class,
|
||||
BeanUtils.toBean(list, Demo01ContactRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.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 Demo01ContactPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "名字", example = "张三")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "性别", example = "1")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.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 Demo01ContactRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21555")
|
||||
@ExcelProperty("编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
|
||||
@ExcelProperty("名字")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty(value = "性别", converter = DictConvert.class)
|
||||
@DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "出生年", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("出生年")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对")
|
||||
@ExcelProperty("简介")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "头像")
|
||||
@ExcelProperty("头像")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 示例联系人新增/修改 Request VO")
|
||||
@Data
|
||||
public class Demo01ContactSaveReqVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21555")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
|
||||
@NotEmpty(message = "名字不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "性别不能为空")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "出生年", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "出生年不能为空")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对")
|
||||
@NotEmpty(message = "简介不能为空")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "头像")
|
||||
private String avatar;
|
||||
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryListReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategorySaveReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo02.Demo02CategoryDO;
|
||||
import cn.iocoder.yudao.module.infra.service.demo.demo02.Demo02CategoryService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Tag(name = "管理后台 - 示例分类")
|
||||
@RestController
|
||||
@RequestMapping("/infra/demo02-category")
|
||||
@Validated
|
||||
public class Demo02CategoryController {
|
||||
|
||||
@Resource
|
||||
private Demo02CategoryService demo02CategoryService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建示例分类")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo02-category:create')")
|
||||
public CommonResult<Long> createDemo02Category(@Valid @RequestBody Demo02CategorySaveReqVO createReqVO) {
|
||||
return success(demo02CategoryService.createDemo02Category(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新示例分类")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo02-category:update')")
|
||||
public CommonResult<Boolean> updateDemo02Category(@Valid @RequestBody Demo02CategorySaveReqVO updateReqVO) {
|
||||
demo02CategoryService.updateDemo02Category(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除示例分类")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo02-category:delete')")
|
||||
public CommonResult<Boolean> deleteDemo02Category(@RequestParam("id") Long id) {
|
||||
demo02CategoryService.deleteDemo02Category(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得示例分类")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo02-category:query')")
|
||||
public CommonResult<Demo02CategoryRespVO> getDemo02Category(@RequestParam("id") Long id) {
|
||||
Demo02CategoryDO demo02Category = demo02CategoryService.getDemo02Category(id);
|
||||
return success(BeanUtils.toBean(demo02Category, Demo02CategoryRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获得示例分类列表")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo02-category:query')")
|
||||
public CommonResult<List<Demo02CategoryRespVO>> getDemo02CategoryList(@Valid Demo02CategoryListReqVO listReqVO) {
|
||||
List<Demo02CategoryDO> list = demo02CategoryService.getDemo02CategoryList(listReqVO);
|
||||
return success(BeanUtils.toBean(list, Demo02CategoryRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出示例分类 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo02-category:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportDemo02CategoryExcel(@Valid Demo02CategoryListReqVO listReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
List<Demo02CategoryDO> list = demo02CategoryService.getDemo02CategoryList(listReqVO);
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "示例分类.xls", "数据", Demo02CategoryRespVO.class,
|
||||
BeanUtils.toBean(list, Demo02CategoryRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 示例分类列表 Request VO")
|
||||
@Data
|
||||
public class Demo02CategoryListReqVO {
|
||||
|
||||
@Schema(description = "名字", example = "芋艿")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "父级编号", example = "6080")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 示例分类 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class Demo02CategoryRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10304")
|
||||
@ExcelProperty("编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
|
||||
@ExcelProperty("名字")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6080")
|
||||
@ExcelProperty("父级编号")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 示例分类新增/修改 Request VO")
|
||||
@Data
|
||||
public class Demo02CategorySaveReqVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10304")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
|
||||
@NotEmpty(message = "名字不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6080")
|
||||
@NotNull(message = "父级编号不能为空")
|
||||
private Long parentId;
|
||||
|
||||
}
|
@ -0,0 +1,197 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentSaveReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
|
||||
import cn.iocoder.yudao.module.infra.service.demo.demo03.Demo03StudentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Tag(name = "管理后台 - 学生")
|
||||
@RestController
|
||||
@RequestMapping("/infra/demo03-student")
|
||||
@Validated
|
||||
public class Demo03StudentController {
|
||||
|
||||
@Resource
|
||||
private Demo03StudentService demo03StudentService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建学生")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:create')")
|
||||
public CommonResult<Long> createDemo03Student(@Valid @RequestBody Demo03StudentSaveReqVO createReqVO) {
|
||||
return success(demo03StudentService.createDemo03Student(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新学生")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:update')")
|
||||
public CommonResult<Boolean> updateDemo03Student(@Valid @RequestBody Demo03StudentSaveReqVO updateReqVO) {
|
||||
demo03StudentService.updateDemo03Student(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除学生")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
|
||||
public CommonResult<Boolean> deleteDemo03Student(@RequestParam("id") Long id) {
|
||||
demo03StudentService.deleteDemo03Student(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得学生")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
|
||||
public CommonResult<Demo03StudentRespVO> getDemo03Student(@RequestParam("id") Long id) {
|
||||
Demo03StudentDO demo03Student = demo03StudentService.getDemo03Student(id);
|
||||
return success(BeanUtils.toBean(demo03Student, Demo03StudentRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得学生分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
|
||||
public CommonResult<PageResult<Demo03StudentRespVO>> getDemo03StudentPage(@Valid Demo03StudentPageReqVO pageReqVO) {
|
||||
PageResult<Demo03StudentDO> pageResult = demo03StudentService.getDemo03StudentPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, Demo03StudentRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出学生 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportDemo03StudentExcel(@Valid Demo03StudentPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<Demo03StudentDO> list = demo03StudentService.getDemo03StudentPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "学生.xls", "数据", Demo03StudentRespVO.class,
|
||||
BeanUtils.toBean(list, Demo03StudentRespVO.class));
|
||||
}
|
||||
|
||||
// ==================== 子表(学生课程) ====================
|
||||
|
||||
@GetMapping("/demo03-course/page")
|
||||
@Operation(summary = "获得学生课程分页")
|
||||
@Parameter(name = "studentId", description = "学生编号")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
|
||||
public CommonResult<PageResult<Demo03CourseDO>> getDemo03CoursePage(PageParam pageReqVO,
|
||||
@RequestParam("studentId") Long studentId) {
|
||||
return success(demo03StudentService.getDemo03CoursePage(pageReqVO, studentId));
|
||||
}
|
||||
|
||||
@PostMapping("/demo03-course/create")
|
||||
@Operation(summary = "创建学生课程")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:create')")
|
||||
public CommonResult<Long> createDemo03Course(@Valid @RequestBody Demo03CourseDO demo03Course) {
|
||||
return success(demo03StudentService.createDemo03Course(demo03Course));
|
||||
}
|
||||
|
||||
@PutMapping("/demo03-course/update")
|
||||
@Operation(summary = "更新学生课程")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:update')")
|
||||
public CommonResult<Boolean> updateDemo03Course(@Valid @RequestBody Demo03CourseDO demo03Course) {
|
||||
demo03StudentService.updateDemo03Course(demo03Course);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/demo03-course/delete")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@Operation(summary = "删除学生课程")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
|
||||
public CommonResult<Boolean> deleteDemo03Course(@RequestParam("id") Long id) {
|
||||
demo03StudentService.deleteDemo03Course(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/demo03-course/get")
|
||||
@Operation(summary = "获得学生课程")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
|
||||
public CommonResult<Demo03CourseDO> getDemo03Course(@RequestParam("id") Long id) {
|
||||
return success(demo03StudentService.getDemo03Course(id));
|
||||
}
|
||||
|
||||
@GetMapping("/demo03-course/list-by-student-id")
|
||||
@Operation(summary = "获得学生课程列表")
|
||||
@Parameter(name = "studentId", description = "学生编号")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
|
||||
public CommonResult<List<Demo03CourseDO>> getDemo03CourseListByStudentId(@RequestParam("studentId") Long studentId) {
|
||||
return success(demo03StudentService.getDemo03CourseListByStudentId(studentId));
|
||||
}
|
||||
|
||||
// ==================== 子表(学生班级) ====================
|
||||
|
||||
@GetMapping("/demo03-grade/page")
|
||||
@Operation(summary = "获得学生班级分页")
|
||||
@Parameter(name = "studentId", description = "学生编号")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
|
||||
public CommonResult<PageResult<Demo03GradeDO>> getDemo03GradePage(PageParam pageReqVO,
|
||||
@RequestParam("studentId") Long studentId) {
|
||||
return success(demo03StudentService.getDemo03GradePage(pageReqVO, studentId));
|
||||
}
|
||||
|
||||
@PostMapping("/demo03-grade/create")
|
||||
@Operation(summary = "创建学生班级")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:create')")
|
||||
public CommonResult<Long> createDemo03Grade(@Valid @RequestBody Demo03GradeDO demo03Grade) {
|
||||
return success(demo03StudentService.createDemo03Grade(demo03Grade));
|
||||
}
|
||||
|
||||
@PutMapping("/demo03-grade/update")
|
||||
@Operation(summary = "更新学生班级")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:update')")
|
||||
public CommonResult<Boolean> updateDemo03Grade(@Valid @RequestBody Demo03GradeDO demo03Grade) {
|
||||
demo03StudentService.updateDemo03Grade(demo03Grade);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/demo03-grade/delete")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@Operation(summary = "删除学生班级")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
|
||||
public CommonResult<Boolean> deleteDemo03Grade(@RequestParam("id") Long id) {
|
||||
demo03StudentService.deleteDemo03Grade(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/demo03-grade/get")
|
||||
@Operation(summary = "获得学生班级")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
|
||||
public CommonResult<Demo03GradeDO> getDemo03Grade(@RequestParam("id") Long id) {
|
||||
return success(demo03StudentService.getDemo03Grade(id));
|
||||
}
|
||||
|
||||
@GetMapping("/demo03-grade/get-by-student-id")
|
||||
@Operation(summary = "获得学生班级")
|
||||
@Parameter(name = "studentId", description = "学生编号")
|
||||
@PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
|
||||
public CommonResult<Demo03GradeDO> getDemo03GradeByStudentId(@RequestParam("studentId") Long studentId) {
|
||||
return success(demo03StudentService.getDemo03GradeByStudentId(studentId));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03;
|
@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo;
|
||||
|
||||
import lombok.*;
|
||||
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 Demo03StudentPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "名字", example = "芋艿")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "性别")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "简介", example = "随便")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
||||
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 Demo03StudentRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8525")
|
||||
@ExcelProperty("编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
|
||||
@ExcelProperty("名字")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty(value = "性别", converter = DictConvert.class)
|
||||
@DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("出生日期")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "随便")
|
||||
@ExcelProperty("简介")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import javax.validation.constraints.*;
|
||||
import java.time.LocalDateTime;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
|
||||
|
||||
@Schema(description = "管理后台 - 学生新增/修改 Request VO")
|
||||
@Data
|
||||
public class Demo03StudentSaveReqVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8525")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
|
||||
@NotEmpty(message = "名字不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "性别不能为空")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "出生日期不能为空")
|
||||
private LocalDateTime birthday;
|
||||
|
||||
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "随便")
|
||||
@NotEmpty(message = "简介不能为空")
|
||||
private String description;
|
||||
|
||||
|
||||
private List<Demo03CourseDO> demo03Courses;
|
||||
|
||||
private Demo03GradeDO demo03Grade;
|
||||
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* 代码生成示例
|
||||
*
|
||||
* 1. demo01:单表(增删改查)
|
||||
* 2. demo02:单表(树形结构)
|
||||
* 3. demo03:主子表(标准模式)+ 主子表(ERP 模式)+ 主子表(内嵌模式)
|
||||
*/
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.demo;
|
@ -0,0 +1,45 @@
|
||||
### 请求 /infra/file-config/create 接口 => 成功
|
||||
POST {{baseUrl}}/infra/file-config/create
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"name": "S3 - 七牛云",
|
||||
"remark": "",
|
||||
"storage": 20,
|
||||
"config": {
|
||||
"accessKey": "b7yvuhBSAGjmtPhMFcn9iMOxUOY_I06cA_p0ZUx8",
|
||||
"accessSecret": "kXM1l5ia1RvSX3QaOEcwI3RLz3Y2rmNszWonKZtP",
|
||||
"bucket": "ruoyi-vue-pro",
|
||||
"endpoint": "s3-cn-south-1.qiniucs.com",
|
||||
"domain": "http://test.yudao.iocoder.cn",
|
||||
"region": "oss-cn-beijing"
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /infra/file-config/update 接口 => 成功
|
||||
PUT {{baseUrl}}/infra/file-config/update
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 2,
|
||||
"name": "S3 - 七牛云",
|
||||
"remark": "",
|
||||
"config": {
|
||||
"accessKey": "b7yvuhBSAGjmtPhMFcn9iMOxUOY_I06cA_p0ZUx8",
|
||||
"accessSecret": "kXM1l5ia1RvSX3QaOEcwI3RLz3Y2rmNszWonKZtP",
|
||||
"bucket": "ruoyi-vue-pro",
|
||||
"endpoint": "s3-cn-south-1.qiniucs.com",
|
||||
"domain": "http://test.yudao.iocoder.cn",
|
||||
"region": "oss-cn-beijing"
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /infra/file-config/test 接口 => 成功
|
||||
GET {{baseUrl}}/infra/file-config/test?id=2
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
@ -0,0 +1,88 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.file;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigSaveReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
|
||||
import cn.iocoder.yudao.module.infra.service.file.FileConfigService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 文件配置")
|
||||
@RestController
|
||||
@RequestMapping("/infra/file-config")
|
||||
@Validated
|
||||
public class FileConfigController {
|
||||
|
||||
@Resource
|
||||
private FileConfigService fileConfigService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建文件配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:create')")
|
||||
public CommonResult<Long> createFileConfig(@Valid @RequestBody FileConfigSaveReqVO createReqVO) {
|
||||
return success(fileConfigService.createFileConfig(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新文件配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:update')")
|
||||
public CommonResult<Boolean> updateFileConfig(@Valid @RequestBody FileConfigSaveReqVO updateReqVO) {
|
||||
fileConfigService.updateFileConfig(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-master")
|
||||
@Operation(summary = "更新文件配置为 Master")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:update')")
|
||||
public CommonResult<Boolean> updateFileConfigMaster(@RequestParam("id") Long id) {
|
||||
fileConfigService.updateFileConfigMaster(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除文件配置")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:delete')")
|
||||
public CommonResult<Boolean> deleteFileConfig(@RequestParam("id") Long id) {
|
||||
fileConfigService.deleteFileConfig(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得文件配置")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:query')")
|
||||
public CommonResult<FileConfigRespVO> getFileConfig(@RequestParam("id") Long id) {
|
||||
FileConfigDO config = fileConfigService.getFileConfig(id);
|
||||
return success(BeanUtils.toBean(config, FileConfigRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得文件配置分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:query')")
|
||||
public CommonResult<PageResult<FileConfigRespVO>> getFileConfigPage(@Valid FileConfigPageReqVO pageVO) {
|
||||
PageResult<FileConfigDO> pageResult = fileConfigService.getFileConfigPage(pageVO);
|
||||
return success(BeanUtils.toBean(pageResult, FileConfigRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/test")
|
||||
@Operation(summary = "测试文件配置是否正确")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:query')")
|
||||
public CommonResult<String> testFileConfig(@RequestParam("id") Long id) throws Exception {
|
||||
String url = fileConfigService.testFileConfig(id);
|
||||
return success(url);
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.file;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
|
||||
import cn.iocoder.yudao.module.infra.service.file.FileService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.PermitAll;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 文件存储")
|
||||
@RestController
|
||||
@RequestMapping("/infra/file")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class FileController {
|
||||
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
|
||||
@PostMapping("/upload")
|
||||
@Operation(summary = "上传文件", description = "模式一:后端上传文件")
|
||||
@OperateLog(logArgs = false) // 上传文件,没有记录操作日志的必要
|
||||
public CommonResult<String> uploadFile(FileUploadReqVO uploadReqVO) throws Exception {
|
||||
MultipartFile file = uploadReqVO.getFile();
|
||||
String path = uploadReqVO.getPath();
|
||||
return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
|
||||
}
|
||||
|
||||
@GetMapping("/presigned-url")
|
||||
@Operation(summary = "获取文件预签名地址", description = "模式二:前端上传文件:用于前端直接上传七牛、阿里云 OSS 等文件存储器")
|
||||
public CommonResult<FilePresignedUrlRespVO> getFilePresignedUrl(@RequestParam("path") String path) throws Exception {
|
||||
return success(fileService.getFilePresignedUrl(path));
|
||||
}
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建文件", description = "模式二:前端上传文件:配合 presigned-url 接口,记录上传了上传的文件")
|
||||
public CommonResult<Long> createFile(@Valid @RequestBody FileCreateReqVO createReqVO) {
|
||||
return success(fileService.createFile(createReqVO));
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除文件")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:file:delete')")
|
||||
public CommonResult<Boolean> deleteFile(@RequestParam("id") Long id) throws Exception {
|
||||
fileService.deleteFile(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/{configId}/get/**")
|
||||
@PermitAll
|
||||
@Operation(summary = "下载文件")
|
||||
@Parameter(name = "configId", description = "配置编号", required = true)
|
||||
public void getFileContent(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@PathVariable("configId") Long configId) throws Exception {
|
||||
// 获取请求的路径
|
||||
String path = StrUtil.subAfter(request.getRequestURI(), "/get/", false);
|
||||
if (StrUtil.isEmpty(path)) {
|
||||
throw new IllegalArgumentException("结尾的 path 路径必须传递");
|
||||
}
|
||||
// 解码,解决中文路径的问题 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/807/
|
||||
path = URLUtil.decode(path);
|
||||
|
||||
// 读取内容
|
||||
byte[] content = fileService.getFileContent(configId, path);
|
||||
if (content == null) {
|
||||
log.warn("[getFileContent][configId({}) path({}) 文件不存在]", configId, path);
|
||||
response.setStatus(HttpStatus.NOT_FOUND.value());
|
||||
return;
|
||||
}
|
||||
ServletUtils.writeAttachment(response, path, content);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得文件分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file:query')")
|
||||
public CommonResult<PageResult<FileRespVO>> getFilePage(@Valid FilePageReqVO pageVO) {
|
||||
PageResult<FileDO> pageResult = fileService.getFilePage(pageVO);
|
||||
return success(BeanUtils.toBean(pageResult, FileRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 文件配置分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class FileConfigPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "配置名", example = "S3 - 阿里云")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "存储器", example = "1")
|
||||
private Integer storage;
|
||||
|
||||
@Schema(description = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.config;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientConfig;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 文件配置 Response VO")
|
||||
@Data
|
||||
public class FileConfigRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "配置名", requiredMode = Schema.RequiredMode.REQUIRED, example = "S3 - 阿里云")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "存储器,参见 FileStorageEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer storage;
|
||||
|
||||
@Schema(description = "是否为主配置", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
private Boolean master;
|
||||
|
||||
@Schema(description = "存储配置", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private FileClientConfig config;
|
||||
|
||||
@Schema(description = "备注", example = "我是备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
|
||||
@Schema(description = "管理后台 - 文件配置创建/修改 Request VO")
|
||||
@Data
|
||||
public class FileConfigSaveReqVO {
|
||||
|
||||
@Schema(description = "编号", example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "配置名", requiredMode = Schema.RequiredMode.REQUIRED, example = "S3 - 阿里云")
|
||||
@NotNull(message = "配置名不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "存储器,参见 FileStorageEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "存储器不能为空")
|
||||
private Integer storage;
|
||||
|
||||
@Schema(description = "存储配置,配置是动态参数,所以使用 Map 接收", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "存储配置不能为空")
|
||||
private Map<String, Object> config;
|
||||
|
||||
@Schema(description = "备注", example = "我是备注")
|
||||
private String remark;
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 文件创建 Request VO")
|
||||
@Data
|
||||
public class FileCreateReqVO {
|
||||
|
||||
@NotNull(message = "文件配置编号不能为空")
|
||||
@Schema(description = "文件配置编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11")
|
||||
private Long configId;
|
||||
|
||||
@NotNull(message = "文件路径不能为空")
|
||||
@Schema(description = "文件路径", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao.jpg")
|
||||
private String path;
|
||||
|
||||
@NotNull(message = "原文件名不能为空")
|
||||
@Schema(description = "原文件名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao.jpg")
|
||||
private String name;
|
||||
|
||||
@NotNull(message = "文件 URL不能为空")
|
||||
@Schema(description = "文件 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/yudao.jpg")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "文件 MIME 类型", example = "application/octet-stream")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "文件大小", example = "2048", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer size;
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 文件分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class FilePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "文件路径,模糊匹配", example = "yudao")
|
||||
private String path;
|
||||
|
||||
@Schema(description = "文件类型,模糊匹配", example = "jpg")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Schema(description = "管理后台 - 文件预签名地址 Response VO")
|
||||
@Data
|
||||
public class FilePresignedUrlRespVO {
|
||||
|
||||
@Schema(description = "配置编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11")
|
||||
private Long configId;
|
||||
|
||||
@Schema(description = "文件上传 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://s3.cn-south-1.qiniucs.com/ruoyi-vue-pro/758d3a5387507358c7236de4c8f96de1c7f5097ff6a7722b34772fb7b76b140f.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=3TvrJ70gl2Gt6IBe7_IZT1F6i_k0iMuRtyEv4EyS%2F20240217%2Fcn-south-1%2Fs3%2Faws4_request&X-Amz-Date=20240217T123222Z&X-Amz-Expires=600&X-Amz-SignedHeaders=host&X-Amz-Signature=a29f33770ab79bf523ccd4034d0752ac545f3c2a3b17baa1eb4e280cfdccfda5")
|
||||
private String uploadUrl;
|
||||
|
||||
/**
|
||||
* 为什么要返回 url 字段?
|
||||
*
|
||||
* 前端上传完文件后,需要使用该 URL 进行访问
|
||||
*/
|
||||
@Schema(description = "文件访问 URL", requiredMode = Schema.RequiredMode.REQUIRED,
|
||||
example = "https://test.yudao.iocoder.cn/758d3a5387507358c7236de4c8f96de1c7f5097ff6a7722b34772fb7b76b140f.png")
|
||||
private String url;
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 文件 Response VO,不返回 content 字段,太大")
|
||||
@Data
|
||||
public class FileRespVO {
|
||||
|
||||
@Schema(description = "文件编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "配置编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11")
|
||||
private Long configId;
|
||||
|
||||
@Schema(description = "文件路径", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao.jpg")
|
||||
private String path;
|
||||
|
||||
@Schema(description = "原文件名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao.jpg")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "文件 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/yudao.jpg")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "文件MIME类型", example = "application/octet-stream")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "文件大小", example = "2048", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer size;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 上传文件 Request VO")
|
||||
@Data
|
||||
public class FileUploadReqVO {
|
||||
|
||||
@Schema(description = "文件附件", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "文件附件不能为空")
|
||||
private MultipartFile file;
|
||||
|
||||
@Schema(description = "文件附件", example = "yudaoyuanma.png")
|
||||
private String path;
|
||||
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.job;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.framework.quartz.core.util.CronUtils;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobPageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobSaveReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO;
|
||||
import cn.iocoder.yudao.module.infra.service.job.JobService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Tag(name = "管理后台 - 定时任务")
|
||||
@RestController
|
||||
@RequestMapping("/infra/job")
|
||||
@Validated
|
||||
public class JobController {
|
||||
|
||||
@Resource
|
||||
private JobService jobService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建定时任务")
|
||||
@PreAuthorize("@ss.hasPermission('infra:job:create')")
|
||||
public CommonResult<Long> createJob(@Valid @RequestBody JobSaveReqVO createReqVO)
|
||||
throws SchedulerException {
|
||||
return success(jobService.createJob(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新定时任务")
|
||||
@PreAuthorize("@ss.hasPermission('infra:job:update')")
|
||||
public CommonResult<Boolean> updateJob(@Valid @RequestBody JobSaveReqVO updateReqVO)
|
||||
throws SchedulerException {
|
||||
jobService.updateJob(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-status")
|
||||
@Operation(summary = "更新定时任务的状态")
|
||||
@Parameters({
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024"),
|
||||
@Parameter(name = "status", description = "状态", required = true, example = "1"),
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('infra:job:update')")
|
||||
public CommonResult<Boolean> updateJobStatus(@RequestParam(value = "id") Long id, @RequestParam("status") Integer status)
|
||||
throws SchedulerException {
|
||||
jobService.updateJobStatus(id, status);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除定时任务")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:job:delete')")
|
||||
public CommonResult<Boolean> deleteJob(@RequestParam("id") Long id)
|
||||
throws SchedulerException {
|
||||
jobService.deleteJob(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/trigger")
|
||||
@Operation(summary = "触发定时任务")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:job:trigger')")
|
||||
public CommonResult<Boolean> triggerJob(@RequestParam("id") Long id) throws SchedulerException {
|
||||
jobService.triggerJob(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得定时任务")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:job:query')")
|
||||
public CommonResult<JobRespVO> getJob(@RequestParam("id") Long id) {
|
||||
JobDO job = jobService.getJob(id);
|
||||
return success(BeanUtils.toBean(job, JobRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得定时任务分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:job:query')")
|
||||
public CommonResult<PageResult<JobRespVO>> getJobPage(@Valid JobPageReqVO pageVO) {
|
||||
PageResult<JobDO> pageResult = jobService.getJobPage(pageVO);
|
||||
return success(BeanUtils.toBean(pageResult, JobRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出定时任务 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('infra:job:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportJobExcel(@Valid JobPageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<JobDO> list = jobService.getJobPage(exportReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "定时任务.xls", "数据", JobRespVO.class,
|
||||
BeanUtils.toBean(list, JobRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/get_next_times")
|
||||
@Operation(summary = "获得定时任务的下 n 次执行时间")
|
||||
@Parameters({
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024"),
|
||||
@Parameter(name = "count", description = "数量", example = "5")
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('infra:job:query')")
|
||||
public CommonResult<List<LocalDateTime>> getJobNextTimes(
|
||||
@RequestParam("id") Long id,
|
||||
@RequestParam(value = "count", required = false, defaultValue = "5") Integer count) {
|
||||
JobDO job = jobService.getJob(id);
|
||||
if (job == null) {
|
||||
return success(Collections.emptyList());
|
||||
}
|
||||
return success(CronUtils.getNextTimes(job.getCronExpression(), count));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.job;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogPageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogRespVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobLogDO;
|
||||
import cn.iocoder.yudao.module.infra.service.job.JobLogService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Tag(name = "管理后台 - 定时任务日志")
|
||||
@RestController
|
||||
@RequestMapping("/infra/job-log")
|
||||
@Validated
|
||||
public class JobLogController {
|
||||
|
||||
@Resource
|
||||
private JobLogService jobLogService;
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得定时任务日志")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('infra:job:query')")
|
||||
public CommonResult<JobLogRespVO> getJobLog(@RequestParam("id") Long id) {
|
||||
JobLogDO jobLog = jobLogService.getJobLog(id);
|
||||
return success(BeanUtils.toBean(jobLog, JobLogRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得定时任务日志分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:job:query')")
|
||||
public CommonResult<PageResult<JobLogRespVO>> getJobLogPage(@Valid JobLogPageReqVO pageVO) {
|
||||
PageResult<JobLogDO> pageResult = jobLogService.getJobLogPage(pageVO);
|
||||
return success(BeanUtils.toBean(pageResult, JobLogRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出定时任务日志 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('infra:job:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportJobLogExcel(@Valid JobLogPageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<JobLogDO> list = jobLogService.getJobLogPage(exportReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "任务日志.xls", "数据", JobLogRespVO.class,
|
||||
BeanUtils.toBean(list, JobLogRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "管理后台 - 定时任务分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class JobPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "任务名称,模糊匹配", example = "测试任务")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "任务状态,参见 JobStatusEnum 枚举", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "处理器的名字,模糊匹配", example = "sysUserSessionTimeoutJob")
|
||||
private String handlerName;
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||
import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 定时任务 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class JobRespVO {
|
||||
|
||||
@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 = "1")
|
||||
@ExcelProperty(value = "任务状态", converter = DictConvert.class)
|
||||
@DictFormat(DictTypeConstants.JOB_STATUS)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "处理器的名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "sysUserSessionTimeoutJob")
|
||||
@ExcelProperty("处理器的名字")
|
||||
private String handlerName;
|
||||
|
||||
@Schema(description = "处理器的参数", example = "yudao")
|
||||
@ExcelProperty("处理器的参数")
|
||||
private String handlerParam;
|
||||
|
||||
@Schema(description = "CRON 表达式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0/10 * * * * ? *")
|
||||
@ExcelProperty("CRON 表达式")
|
||||
private String cronExpression;
|
||||
|
||||
@Schema(description = "重试次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
|
||||
@NotNull(message = "重试次数不能为空")
|
||||
private Integer retryCount;
|
||||
|
||||
@Schema(description = "重试间隔", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
|
||||
private Integer retryInterval;
|
||||
|
||||
@Schema(description = "监控超时时间", example = "1000")
|
||||
@ExcelProperty("监控超时时间")
|
||||
private Integer monitorTimeout;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 定时任务创建/修改 Request VO")
|
||||
@Data
|
||||
public class JobSaveReqVO {
|
||||
|
||||
@Schema(description = "任务编号", example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "任务名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试任务")
|
||||
@NotEmpty(message = "任务名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "处理器的名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "sysUserSessionTimeoutJob")
|
||||
@NotEmpty(message = "处理器的名字不能为空")
|
||||
private String handlerName;
|
||||
|
||||
@Schema(description = "处理器的参数", example = "yudao")
|
||||
private String handlerParam;
|
||||
|
||||
@Schema(description = "CRON 表达式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0/10 * * * * ? *")
|
||||
@NotEmpty(message = "CRON 表达式不能为空")
|
||||
private String cronExpression;
|
||||
|
||||
@Schema(description = "重试次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
|
||||
@NotNull(message = "重试次数不能为空")
|
||||
private Integer retryCount;
|
||||
|
||||
@Schema(description = "重试间隔", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
|
||||
@NotNull(message = "重试间隔不能为空")
|
||||
private Integer retryInterval;
|
||||
|
||||
@Schema(description = "监控超时时间", example = "1000")
|
||||
private Integer monitorTimeout;
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 定时任务日志分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class JobLogPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "任务编号", example = "10")
|
||||
private Long jobId;
|
||||
|
||||
@Schema(description = "处理器的名字,模糊匹配")
|
||||
private String handlerName;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@Schema(description = "开始执行时间")
|
||||
private LocalDateTime beginTime;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@Schema(description = "结束执行时间")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "任务状态,参见 JobLogStatusEnum 枚举")
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||
import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 定时任务日志 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class JobLogRespVO {
|
||||
|
||||
@Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@ExcelProperty("日志编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@ExcelProperty("任务编号")
|
||||
private Long jobId;
|
||||
|
||||
@Schema(description = "处理器的名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "sysUserSessionTimeoutJob")
|
||||
@ExcelProperty("处理器的名字")
|
||||
private String handlerName;
|
||||
|
||||
@Schema(description = "处理器的参数", example = "yudao")
|
||||
@ExcelProperty("处理器的参数")
|
||||
private String handlerParam;
|
||||
|
||||
@Schema(description = "第几次执行", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty("第几次执行")
|
||||
private Integer executeIndex;
|
||||
|
||||
@Schema(description = "开始执行时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("开始执行时间")
|
||||
private LocalDateTime beginTime;
|
||||
|
||||
@Schema(description = "结束执行时间")
|
||||
@ExcelProperty("结束执行时间")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "执行时长", example = "123")
|
||||
@ExcelProperty("执行时长")
|
||||
private Integer duration;
|
||||
|
||||
@Schema(description = "任务状态,参见 JobLogStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty(value = "任务状态", converter = DictConvert.class)
|
||||
@DictFormat(DictTypeConstants.JOB_STATUS)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "结果数据", example = "执行成功")
|
||||
@ExcelProperty("结果数据")
|
||||
private String result;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.logger;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogPageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogRespVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO;
|
||||
import cn.iocoder.yudao.module.infra.service.logger.ApiAccessLogService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Tag(name = "管理后台 - API 访问日志")
|
||||
@RestController
|
||||
@RequestMapping("/infra/api-access-log")
|
||||
@Validated
|
||||
public class ApiAccessLogController {
|
||||
|
||||
@Resource
|
||||
private ApiAccessLogService apiAccessLogService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得API 访问日志分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:api-access-log:query')")
|
||||
public CommonResult<PageResult<ApiAccessLogRespVO>> getApiAccessLogPage(@Valid ApiAccessLogPageReqVO pageReqVO) {
|
||||
PageResult<ApiAccessLogDO> pageResult = apiAccessLogService.getApiAccessLogPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, ApiAccessLogRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出API 访问日志 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('infra:api-access-log:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportApiAccessLogExcel(@Valid ApiAccessLogPageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<ApiAccessLogDO> list = apiAccessLogService.getApiAccessLogPage(exportReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "API 访问日志.xls", "数据", ApiAccessLogRespVO.class,
|
||||
BeanUtils.toBean(list, ApiAccessLogRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.logger;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogPageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogRespVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO;
|
||||
import cn.iocoder.yudao.module.infra.service.logger.ApiErrorLogService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "管理后台 - API 错误日志")
|
||||
@RestController
|
||||
@RequestMapping("/infra/api-error-log")
|
||||
@Validated
|
||||
public class ApiErrorLogController {
|
||||
|
||||
@Resource
|
||||
private ApiErrorLogService apiErrorLogService;
|
||||
|
||||
@PutMapping("/update-status")
|
||||
@Operation(summary = "更新 API 错误日志的状态")
|
||||
@Parameters({
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024"),
|
||||
@Parameter(name = "processStatus", description = "处理状态", required = true, example = "1")
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('infra:api-error-log:update-status')")
|
||||
public CommonResult<Boolean> updateApiErrorLogProcess(@RequestParam("id") Long id,
|
||||
@RequestParam("processStatus") Integer processStatus) {
|
||||
apiErrorLogService.updateApiErrorLogProcess(id, processStatus, getLoginUserId());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得 API 错误日志分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:api-error-log:query')")
|
||||
public CommonResult<PageResult<ApiErrorLogRespVO>> getApiErrorLogPage(@Valid ApiErrorLogPageReqVO pageReqVO) {
|
||||
PageResult<ApiErrorLogDO> pageResult = apiErrorLogService.getApiErrorLogPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, ApiErrorLogRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出 API 错误日志 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('infra:api-error-log:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportApiErrorLogExcel(@Valid ApiErrorLogPageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<ApiErrorLogDO> list = apiErrorLogService.getApiErrorLogPage(exportReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "API 错误日志.xls", "数据", ApiErrorLogRespVO.class,
|
||||
BeanUtils.toBean(list, ApiErrorLogRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - API 访问日志分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class ApiAccessLogPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "用户编号", example = "666")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户类型", example = "2")
|
||||
private Integer userType;
|
||||
|
||||
@Schema(description = "应用名", example = "dashboard")
|
||||
private String applicationName;
|
||||
|
||||
@Schema(description = "请求地址,模糊匹配", example = "/xxx/yyy")
|
||||
private String requestUrl;
|
||||
|
||||
@Schema(description = "开始时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] beginTime;
|
||||
|
||||
@Schema(description = "执行时长,大于等于,单位:毫秒", example = "100")
|
||||
private Integer duration;
|
||||
|
||||
@Schema(description = "结果码", example = "0")
|
||||
private Integer resultCode;
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||
import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - API 访问日志 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class ApiAccessLogRespVO {
|
||||
|
||||
@Schema(description = "日志主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@ExcelProperty("日志主键")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "链路追踪编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "66600cb6-7852-11eb-9439-0242ac130002")
|
||||
@ExcelProperty("链路追踪编号")
|
||||
private String traceId;
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
|
||||
@ExcelProperty("用户编号")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@ExcelProperty(value = "用户类型", converter = DictConvert.class)
|
||||
@DictFormat(DictTypeConstants.USER_TYPE)
|
||||
private Integer userType;
|
||||
|
||||
@Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "dashboard")
|
||||
@ExcelProperty("应用名")
|
||||
private String applicationName;
|
||||
|
||||
@Schema(description = "请求方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "GET")
|
||||
@ExcelProperty("请求方法名")
|
||||
private String requestMethod;
|
||||
|
||||
@Schema(description = "请求地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "/xxx/yyy")
|
||||
@ExcelProperty("请求地址")
|
||||
private String requestUrl;
|
||||
|
||||
@Schema(description = "请求参数")
|
||||
@ExcelProperty("请求参数")
|
||||
private String requestParams;
|
||||
|
||||
@Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1")
|
||||
@ExcelProperty("用户 IP")
|
||||
private String userIp;
|
||||
|
||||
@Schema(description = "浏览器 UA", requiredMode = Schema.RequiredMode.REQUIRED, example = "Mozilla/5.0")
|
||||
@ExcelProperty("浏览器 UA")
|
||||
private String userAgent;
|
||||
|
||||
@Schema(description = "开始请求时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("开始请求时间")
|
||||
private LocalDateTime beginTime;
|
||||
|
||||
@Schema(description = "结束请求时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("结束请求时间")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "执行时长", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
@ExcelProperty("执行时长")
|
||||
private Integer duration;
|
||||
|
||||
@Schema(description = "结果码", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@ExcelProperty("结果码")
|
||||
private Integer resultCode;
|
||||
|
||||
@Schema(description = "结果提示", example = "芋道源码,牛逼!")
|
||||
@ExcelProperty("结果提示")
|
||||
private String resultMsg;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - API 错误日志分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class ApiErrorLogPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "用户编号", example = "666")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户类型", example = "1")
|
||||
private Integer userType;
|
||||
|
||||
@Schema(description = "应用名", example = "dashboard")
|
||||
private String applicationName;
|
||||
|
||||
@Schema(description = "请求地址", example = "/xx/yy")
|
||||
private String requestUrl;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@Schema(description = "异常发生时间")
|
||||
private LocalDateTime[] exceptionTime;
|
||||
|
||||
@Schema(description = "处理状态", example = "0")
|
||||
private Integer processStatus;
|
||||
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||
import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - API 错误日志 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class ApiErrorLogRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@ExcelProperty("编号")
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "链路追踪编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "66600cb6-7852-11eb-9439-0242ac130002")
|
||||
@ExcelProperty("链路追踪编号")
|
||||
private String traceId;
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
|
||||
@ExcelProperty("用户编号")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty(value = "用户类型", converter = DictConvert.class)
|
||||
@DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_TYPE)
|
||||
private Integer userType;
|
||||
|
||||
@Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "dashboard")
|
||||
@ExcelProperty("应用名")
|
||||
private String applicationName;
|
||||
|
||||
@Schema(description = "请求方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "GET")
|
||||
@ExcelProperty("请求方法名")
|
||||
private String requestMethod;
|
||||
|
||||
@Schema(description = "请求地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "/xx/yy")
|
||||
@ExcelProperty("请求地址")
|
||||
private String requestUrl;
|
||||
|
||||
@Schema(description = "请求参数", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("请求参数")
|
||||
private String requestParams;
|
||||
|
||||
@Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1")
|
||||
@ExcelProperty("用户 IP")
|
||||
private String userIp;
|
||||
|
||||
@Schema(description = "浏览器 UA", requiredMode = Schema.RequiredMode.REQUIRED, example = "Mozilla/5.0")
|
||||
@ExcelProperty("浏览器 UA")
|
||||
private String userAgent;
|
||||
|
||||
@Schema(description = "异常发生时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("异常发生时间")
|
||||
private LocalDateTime exceptionTime;
|
||||
|
||||
@Schema(description = "异常名", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("异常名")
|
||||
private String exceptionName;
|
||||
|
||||
@Schema(description = "异常导致的消息", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("异常导致的消息")
|
||||
private String exceptionMessage;
|
||||
|
||||
@Schema(description = "异常导致的根消息", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("异常导致的根消息")
|
||||
private String exceptionRootCauseMessage;
|
||||
|
||||
@Schema(description = "异常的栈轨迹", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("异常的栈轨迹")
|
||||
private String exceptionStackTrace;
|
||||
|
||||
@Schema(description = "异常发生的类全名", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("异常发生的类全名")
|
||||
private String exceptionClassName;
|
||||
|
||||
@Schema(description = "异常发生的类文件", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("异常发生的类文件")
|
||||
private String exceptionFileName;
|
||||
|
||||
@Schema(description = "异常发生的方法名", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("异常发生的方法名")
|
||||
private String exceptionMethodName;
|
||||
|
||||
@Schema(description = "异常发生的方法所在行", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("异常发生的方法所在行")
|
||||
private Integer exceptionLineNumber;
|
||||
|
||||
@Schema(description = "处理状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@ExcelProperty(value = "处理状态", converter = DictConvert.class)
|
||||
@DictFormat(DictTypeConstants.API_ERROR_LOG_PROCESS_STATUS)
|
||||
private Integer processStatus;
|
||||
|
||||
@Schema(description = "处理时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("处理时间")
|
||||
private LocalDateTime processTime;
|
||||
|
||||
@Schema(description = "处理用户编号", example = "233")
|
||||
@ExcelProperty("处理用户编号")
|
||||
private Integer processUserId;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
### 请求 /infra/redis/get-monitor-info 接口 => 成功
|
||||
GET {{baseUrl}}/infra/redis/get-monitor-info
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
@ -0,0 +1,43 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.redis;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO;
|
||||
import cn.iocoder.yudao.module.infra.convert.redis.RedisConvert;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.data.redis.connection.RedisServerCommands;
|
||||
import org.springframework.data.redis.core.RedisCallback;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Properties;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - Redis 监控")
|
||||
@RestController
|
||||
@RequestMapping("/infra/redis")
|
||||
public class RedisController {
|
||||
|
||||
@Resource
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
@GetMapping("/get-monitor-info")
|
||||
@Operation(summary = "获得 Redis 监控信息")
|
||||
@PreAuthorize("@ss.hasPermission('infra:redis:get-monitor-info')")
|
||||
public CommonResult<RedisMonitorRespVO> getRedisMonitorInfo() {
|
||||
// 获得 Redis 统计信息
|
||||
Properties info = stringRedisTemplate.execute((RedisCallback<Properties>) RedisServerCommands::info);
|
||||
Long dbSize = stringRedisTemplate.execute(RedisServerCommands::dbSize);
|
||||
Properties commandStats = stringRedisTemplate.execute((
|
||||
RedisCallback<Properties>) connection -> connection.info("commandstats"));
|
||||
assert commandStats != null; // 断言,避免警告
|
||||
// 拼接结果返回
|
||||
return success(RedisConvert.INSTANCE.build(info, dbSize, commandStats));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.redis.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
@Schema(description = "管理后台 - Redis 监控信息 Response VO")
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class RedisMonitorRespVO {
|
||||
|
||||
@Schema(description = "Redis info 指令结果,具体字段,查看 Redis 文档", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Properties info;
|
||||
|
||||
@Schema(description = "Redis key 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long dbSize;
|
||||
|
||||
@Schema(description = "CommandStat 数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<CommandStat> commandStats;
|
||||
|
||||
@Schema(description = "Redis 命令统计结果")
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public static class CommandStat {
|
||||
|
||||
@Schema(description = "Redis 命令", requiredMode = Schema.RequiredMode.REQUIRED, example = "get")
|
||||
private String command;
|
||||
|
||||
@Schema(description = "调用次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long calls;
|
||||
|
||||
@Schema(description = "消耗 CPU 秒数", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
|
||||
private Long usec;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.app.file;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.infra.controller.app.file.vo.AppFileUploadReqVO;
|
||||
import cn.iocoder.yudao.module.infra.service.file.FileService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "用户 App - 文件存储")
|
||||
@RestController
|
||||
@RequestMapping("/infra/file")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class AppFileController {
|
||||
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
|
||||
@PostMapping("/upload")
|
||||
@Operation(summary = "上传文件")
|
||||
public CommonResult<String> uploadFile(AppFileUploadReqVO uploadReqVO) throws Exception {
|
||||
MultipartFile file = uploadReqVO.getFile();
|
||||
String path = uploadReqVO.getPath();
|
||||
return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.app.file.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "用户 App - 上传文件 Request VO")
|
||||
@Data
|
||||
public class AppFileUploadReqVO {
|
||||
|
||||
@Schema(description = "文件附件", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "文件附件不能为空")
|
||||
private MultipartFile file;
|
||||
|
||||
@Schema(description = "文件附件", example = "yudaoyuanma.png")
|
||||
private String path;
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* 占位
|
||||
*/
|
||||
package cn.iocoder.yudao.module.infra.controller.app;
|
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* 提供 RESTful API 给前端:
|
||||
* 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目
|
||||
* 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分
|
||||
*/
|
||||
package cn.iocoder.yudao.module.infra.controller;
|
@ -0,0 +1,69 @@
|
||||
package cn.iocoder.yudao.module.infra.convert.codegen;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenDetailRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenPreviewRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.column.CodegenColumnRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTableRespVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableField;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.Named;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface CodegenConvert {
|
||||
|
||||
CodegenConvert INSTANCE = Mappers.getMapper(CodegenConvert.class);
|
||||
|
||||
// ========== TableInfo 相关 ==========
|
||||
|
||||
@Mappings({
|
||||
@Mapping(source = "name", target = "tableName"),
|
||||
@Mapping(source = "comment", target = "tableComment"),
|
||||
})
|
||||
CodegenTableDO convert(TableInfo bean);
|
||||
|
||||
List<CodegenColumnDO> convertList(List<TableField> list);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(source = "name", target = "columnName"),
|
||||
@Mapping(source = "metaInfo.jdbcType", target = "dataType", qualifiedByName = "getDataType"),
|
||||
@Mapping(source = "comment", target = "columnComment"),
|
||||
@Mapping(source = "metaInfo.nullable", target = "nullable"),
|
||||
@Mapping(source = "keyFlag", target = "primaryKey"),
|
||||
@Mapping(source = "keyIdentityFlag", target = "autoIncrement"),
|
||||
@Mapping(source = "columnType.type", target = "javaType"),
|
||||
@Mapping(source = "propertyName", target = "javaField"),
|
||||
})
|
||||
CodegenColumnDO convert(TableField bean);
|
||||
|
||||
@Named("getDataType")
|
||||
default String getDataType(JdbcType jdbcType) {
|
||||
return jdbcType.name();
|
||||
}
|
||||
|
||||
// ========== 其它 ==========
|
||||
|
||||
default CodegenDetailRespVO convert(CodegenTableDO table, List<CodegenColumnDO> columns) {
|
||||
CodegenDetailRespVO respVO = new CodegenDetailRespVO();
|
||||
respVO.setTable(BeanUtils.toBean(table, CodegenTableRespVO.class));
|
||||
respVO.setColumns(BeanUtils.toBean(columns, CodegenColumnRespVO.class));
|
||||
return respVO;
|
||||
}
|
||||
|
||||
default List<CodegenPreviewRespVO> convert(Map<String, String> codes) {
|
||||
return CollectionUtils.convertList(codes.entrySet(),
|
||||
entry -> new CodegenPreviewRespVO().setFilePath(entry.getKey()).setCode(entry.getValue()));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.infra.convert.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigSaveReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ConfigConvert {
|
||||
|
||||
ConfigConvert INSTANCE = Mappers.getMapper(ConfigConvert.class);
|
||||
|
||||
PageResult<ConfigRespVO> convertPage(PageResult<ConfigDO> page);
|
||||
|
||||
List<ConfigRespVO> convertList(List<ConfigDO> list);
|
||||
|
||||
@Mapping(source = "configKey", target = "key")
|
||||
ConfigRespVO convert(ConfigDO bean);
|
||||
|
||||
@Mapping(source = "key", target = "configKey")
|
||||
ConfigDO convert(ConfigSaveReqVO bean);
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.infra.convert.file;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigSaveReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* 文件配置 Convert
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface FileConfigConvert {
|
||||
|
||||
FileConfigConvert INSTANCE = Mappers.getMapper(FileConfigConvert.class);
|
||||
|
||||
@Mapping(target = "config", ignore = true)
|
||||
FileConfigDO convert(FileConfigSaveReqVO bean);
|
||||
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* 提供 POJO 类的实体转换
|
||||
*
|
||||
* 目前使用 MapStruct 框架
|
||||
*/
|
||||
package cn.iocoder.yudao.module.infra.convert;
|
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.infra.convert.redis;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Properties;
|
||||
|
||||
@Mapper
|
||||
public interface RedisConvert {
|
||||
|
||||
RedisConvert INSTANCE = Mappers.getMapper(RedisConvert.class);
|
||||
|
||||
default RedisMonitorRespVO build(Properties info, Long dbSize, Properties commandStats) {
|
||||
RedisMonitorRespVO respVO = RedisMonitorRespVO.builder().info(info).dbSize(dbSize)
|
||||
.commandStats(new ArrayList<>(commandStats.size())).build();
|
||||
commandStats.forEach((key, value) -> {
|
||||
respVO.getCommandStats().add(RedisMonitorRespVO.CommandStat.builder()
|
||||
.command(StrUtil.subAfter((String) key, "cmdstat_", false))
|
||||
.calls(Long.valueOf(StrUtil.subBetween((String) value, "calls=", ",")))
|
||||
.usec(Long.valueOf(StrUtil.subBetween((String) value, "usec=", ",")))
|
||||
.build());
|
||||
});
|
||||
return respVO;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
<http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao>
|
@ -0,0 +1,142 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.codegen;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnHtmlTypeEnum;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnListConditionEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableField;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 代码生成 column 字段定义
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "infra_codegen_column", autoResultMap = true)
|
||||
@KeySequence("infra_codegen_column_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CodegenColumnDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* ID 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 表编号
|
||||
* <p>
|
||||
* 关联 {@link CodegenTableDO#getId()}
|
||||
*/
|
||||
private Long tableId;
|
||||
|
||||
// ========== 表相关字段 ==========
|
||||
|
||||
/**
|
||||
* 字段名
|
||||
*
|
||||
* 关联 {@link TableField#getName()}
|
||||
*/
|
||||
private String columnName;
|
||||
/**
|
||||
* 数据库字段类型
|
||||
*
|
||||
* 关联 {@link TableField.MetaInfo#getJdbcType()}
|
||||
*/
|
||||
private String dataType;
|
||||
/**
|
||||
* 字段描述
|
||||
*
|
||||
* 关联 {@link TableField#getComment()}
|
||||
*/
|
||||
private String columnComment;
|
||||
/**
|
||||
* 是否允许为空
|
||||
*
|
||||
* 关联 {@link TableField.MetaInfo#isNullable()}
|
||||
*/
|
||||
private Boolean nullable;
|
||||
/**
|
||||
* 是否主键
|
||||
*
|
||||
* 关联 {@link TableField#isKeyFlag()}
|
||||
*/
|
||||
private Boolean primaryKey;
|
||||
/**
|
||||
* 是否自增
|
||||
*
|
||||
* 关联 {@link TableField#isKeyIdentityFlag()}
|
||||
*/
|
||||
private Boolean autoIncrement;
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer ordinalPosition;
|
||||
|
||||
// ========== Java 相关字段 ==========
|
||||
|
||||
/**
|
||||
* Java 属性类型
|
||||
*
|
||||
* 例如说 String、Boolean 等等
|
||||
*
|
||||
* 关联 {@link TableField#getColumnType()}
|
||||
*/
|
||||
private String javaType;
|
||||
/**
|
||||
* Java 属性名
|
||||
*
|
||||
* 关联 {@link TableField#getPropertyName()}
|
||||
*/
|
||||
private String javaField;
|
||||
/**
|
||||
* 字典类型
|
||||
* <p>
|
||||
* 关联 DictTypeDO 的 type 属性
|
||||
*/
|
||||
private String dictType;
|
||||
/**
|
||||
* 数据示例,主要用于生成 Swagger 注解的 example 字段
|
||||
*/
|
||||
private String example;
|
||||
|
||||
// ========== CRUD 相关字段 ==========
|
||||
|
||||
/**
|
||||
* 是否为 Create 创建操作的字段
|
||||
*/
|
||||
private Boolean createOperation;
|
||||
/**
|
||||
* 是否为 Update 更新操作的字段
|
||||
*/
|
||||
private Boolean updateOperation;
|
||||
/**
|
||||
* 是否为 List 查询操作的字段
|
||||
*/
|
||||
private Boolean listOperation;
|
||||
/**
|
||||
* List 查询操作的条件类型
|
||||
* <p>
|
||||
* 枚举 {@link CodegenColumnListConditionEnum}
|
||||
*/
|
||||
private String listOperationCondition;
|
||||
/**
|
||||
* 是否为 List 查询操作的返回字段
|
||||
*/
|
||||
private Boolean listOperationResult;
|
||||
|
||||
// ========== UI 相关字段 ==========
|
||||
|
||||
/**
|
||||
* 显示类型
|
||||
* <p>
|
||||
* 枚举 {@link CodegenColumnHtmlTypeEnum}
|
||||
*/
|
||||
private String htmlType;
|
||||
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.codegen;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 代码生成 table 表定义
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "infra_codegen_table", autoResultMap = true)
|
||||
@KeySequence("infra_codegen_table_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CodegenTableDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* ID 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 数据源编号
|
||||
*
|
||||
* 关联 {@link DataSourceConfigDO#getId()}
|
||||
*/
|
||||
private Long dataSourceConfigId;
|
||||
/**
|
||||
* 生成场景
|
||||
*
|
||||
* 枚举 {@link CodegenSceneEnum}
|
||||
*/
|
||||
private Integer scene;
|
||||
|
||||
// ========== 表相关字段 ==========
|
||||
|
||||
/**
|
||||
* 表名称
|
||||
*
|
||||
* 关联 {@link TableInfo#getName()}
|
||||
*/
|
||||
private String tableName;
|
||||
/**
|
||||
* 表描述
|
||||
*
|
||||
* 关联 {@link TableInfo#getComment()}
|
||||
*/
|
||||
private String tableComment;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
// ========== 类相关字段 ==========
|
||||
|
||||
/**
|
||||
* 模块名,即一级目录
|
||||
*
|
||||
* 例如说,system、infra、tool 等等
|
||||
*/
|
||||
private String moduleName;
|
||||
/**
|
||||
* 业务名,即二级目录
|
||||
*
|
||||
* 例如说,user、permission、dict 等等
|
||||
*/
|
||||
private String businessName;
|
||||
/**
|
||||
* 类名称(首字母大写)
|
||||
*
|
||||
* 例如说,SysUser、SysMenu、SysDictData 等等
|
||||
*/
|
||||
private String className;
|
||||
/**
|
||||
* 类描述
|
||||
*/
|
||||
private String classComment;
|
||||
/**
|
||||
* 作者
|
||||
*/
|
||||
private String author;
|
||||
|
||||
// ========== 生成相关字段 ==========
|
||||
|
||||
/**
|
||||
* 模板类型
|
||||
*
|
||||
* 枚举 {@link CodegenTemplateTypeEnum}
|
||||
*/
|
||||
private Integer templateType;
|
||||
/**
|
||||
* 代码生成的前端类型
|
||||
*
|
||||
* 枚举 {@link CodegenFrontTypeEnum}
|
||||
*/
|
||||
private Integer frontType;
|
||||
|
||||
// ========== 菜单相关字段 ==========
|
||||
|
||||
/**
|
||||
* 父菜单编号
|
||||
*
|
||||
* 关联 MenuDO 的 id 属性
|
||||
*/
|
||||
private Long parentMenuId;
|
||||
|
||||
// ========== 主子表相关字段 ==========
|
||||
|
||||
/**
|
||||
* 主表的编号
|
||||
*
|
||||
* 关联 {@link CodegenTableDO#getId()}
|
||||
*/
|
||||
private Long masterTableId;
|
||||
/**
|
||||
* 【自己】子表关联主表的字段编号
|
||||
*
|
||||
* 关联 {@link CodegenColumnDO#getId()}
|
||||
*/
|
||||
private Long subJoinColumnId;
|
||||
/**
|
||||
* 主表与子表是否一对多
|
||||
*
|
||||
* true:一对多
|
||||
* false:一对一
|
||||
*/
|
||||
private Boolean subJoinMany;
|
||||
|
||||
// ========== 树表相关字段 ==========
|
||||
|
||||
/**
|
||||
* 树表的父字段编号
|
||||
*
|
||||
* 关联 {@link CodegenColumnDO#getId()}
|
||||
*/
|
||||
private Long treeParentColumnId;
|
||||
/**
|
||||
* 树表的名字字段编号
|
||||
*
|
||||
* 名字的用途:新增或修改时,select 框展示的字段
|
||||
*
|
||||
* 关联 {@link CodegenColumnDO#getId()}
|
||||
*/
|
||||
private Long treeNameColumnId;
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.infra.enums.config.ConfigTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* 参数配置表
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_config")
|
||||
@KeySequence("infra_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class ConfigDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 参数主键
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 参数分类
|
||||
*/
|
||||
private String category;
|
||||
/**
|
||||
* 参数名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 参数键名
|
||||
*
|
||||
* 支持多 DB 类型时,无法直接使用 key + @TableField("config_key") 来实现转换,原因是 "config_key" AS key 而存在报错
|
||||
*/
|
||||
private String configKey;
|
||||
/**
|
||||
* 参数键值
|
||||
*/
|
||||
private String value;
|
||||
/**
|
||||
* 参数类型
|
||||
*
|
||||
* 枚举 {@link ConfigTypeEnum}
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 是否可见
|
||||
*
|
||||
* 不可见的参数,一般是敏感参数,前端不可获取
|
||||
*/
|
||||
private Boolean visible;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.db;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.EncryptTypeHandler;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 数据源配置
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "infra_data_source_config", autoResultMap = true)
|
||||
@KeySequence("infra_data_source_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
public class DataSourceConfigDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 主键编号 - Master 数据源
|
||||
*/
|
||||
public static final Long ID_MASTER = 0L;
|
||||
|
||||
/**
|
||||
* 主键编号
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 连接名
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 数据源连接
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@TableField(typeHandler = EncryptTypeHandler.class)
|
||||
private String password;
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo01;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
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_demo01_contact")
|
||||
@KeySequence("infra_demo01_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Demo01ContactDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 性别
|
||||
*
|
||||
* 枚举 {@link TODO system_user_sex 对应的类}
|
||||
*/
|
||||
private Integer sex;
|
||||
/**
|
||||
* 出生年
|
||||
*/
|
||||
private LocalDateTime birthday;
|
||||
/**
|
||||
* 简介
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo02;
|
||||
|
||||
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_demo02_category")
|
||||
@KeySequence("infra_demo02_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Demo02CategoryDO extends BaseDO {
|
||||
|
||||
public static final Long PARENT_ID_ROOT = 0L;
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 父级编号
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03;
|
||||
|
||||
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_demo03_course")
|
||||
@KeySequence("infra_demo03_course_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Demo03CourseDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 学生编号
|
||||
*/
|
||||
private Long studentId;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 分数
|
||||
*/
|
||||
private Integer score;
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03;
|
||||
|
||||
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_demo03_grade")
|
||||
@KeySequence("infra_demo03_grade_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Demo03GradeDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 学生编号
|
||||
*/
|
||||
private Long studentId;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 班主任
|
||||
*/
|
||||
private String teacher;
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
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_demo03_student")
|
||||
@KeySequence("infra_demo03_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Demo03StudentDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 性别
|
||||
*
|
||||
* 枚举 {@link TODO system_user_sex 对应的类}
|
||||
*/
|
||||
private Integer sex;
|
||||
/**
|
||||
* 出生日期
|
||||
*/
|
||||
private LocalDateTime birthday;
|
||||
/**
|
||||
* 简介
|
||||
*/
|
||||
private String description;
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.file;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientConfig;
|
||||
import cn.iocoder.yudao.module.infra.framework.file.core.client.db.DBFileClientConfig;
|
||||
import cn.iocoder.yudao.module.infra.framework.file.core.client.ftp.FtpFileClientConfig;
|
||||
import cn.iocoder.yudao.module.infra.framework.file.core.client.local.LocalFileClientConfig;
|
||||
import cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig;
|
||||
import cn.iocoder.yudao.module.infra.framework.file.core.client.sftp.SftpFileClientConfig;
|
||||
import cn.iocoder.yudao.module.infra.framework.file.core.enums.FileStorageEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 文件配置表
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "infra_file_config", autoResultMap = true)
|
||||
@KeySequence("infra_file_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class FileConfigDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 配置编号,数据库自增
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 配置名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 存储器
|
||||
*
|
||||
* 枚举 {@link FileStorageEnum}
|
||||
*/
|
||||
private Integer storage;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
/**
|
||||
* 是否为主配置
|
||||
*
|
||||
* 由于我们可以配置多个文件配置,默认情况下,使用主配置进行文件的上传
|
||||
*/
|
||||
private Boolean master;
|
||||
|
||||
/**
|
||||
* 支付渠道配置
|
||||
*/
|
||||
@TableField(typeHandler = FileClientConfigTypeHandler.class)
|
||||
private FileClientConfig config;
|
||||
|
||||
public static class FileClientConfigTypeHandler extends AbstractJsonTypeHandler<Object> {
|
||||
|
||||
@Override
|
||||
protected Object parse(String json) {
|
||||
FileClientConfig config = JsonUtils.parseObjectQuietly(json, new TypeReference<FileClientConfig>() {});
|
||||
if (config != null) {
|
||||
return config;
|
||||
}
|
||||
|
||||
// 兼容老版本的包路径
|
||||
String className = JsonUtils.parseObject(json, "@class", String.class);
|
||||
className = StrUtil.subAfter(className, ".", true);
|
||||
switch (className) {
|
||||
case "DBFileClientConfig":
|
||||
return JsonUtils.parseObject2(json, DBFileClientConfig.class);
|
||||
case "FtpFileClientConfig":
|
||||
return JsonUtils.parseObject2(json, FtpFileClientConfig.class);
|
||||
case "LocalFileClientConfig":
|
||||
return JsonUtils.parseObject2(json, LocalFileClientConfig.class);
|
||||
case "SftpFileClientConfig":
|
||||
return JsonUtils.parseObject2(json, SftpFileClientConfig.class);
|
||||
case "S3FileClientConfig":
|
||||
return JsonUtils.parseObject2(json, S3FileClientConfig.class);
|
||||
default:
|
||||
throw new IllegalArgumentException("未知的 FileClientConfig 类型:" + json);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toJson(Object obj) {
|
||||
return JsonUtils.toJsonString(obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.file;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.infra.framework.file.core.client.db.DBFileClient;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 文件内容表
|
||||
*
|
||||
* 专门用于存储 {@link DBFileClient} 的文件内容
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_file_content")
|
||||
@KeySequence("infra_file_content_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class FileContentDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号,数据库自增
|
||||
*/
|
||||
@TableId(type = IdType.INPUT)
|
||||
private String id;
|
||||
/**
|
||||
* 配置编号
|
||||
*
|
||||
* 关联 {@link FileConfigDO#getId()}
|
||||
*/
|
||||
private Long configId;
|
||||
/**
|
||||
* 路径,即文件名
|
||||
*/
|
||||
private String path;
|
||||
/**
|
||||
* 文件内容
|
||||
*/
|
||||
private byte[] content;
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.file;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 文件表
|
||||
* 每次文件上传,都会记录一条记录到该表中
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_file")
|
||||
@KeySequence("infra_file_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class FileDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号,数据库自增
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 配置编号
|
||||
*
|
||||
* 关联 {@link FileConfigDO#getId()}
|
||||
*/
|
||||
private Long configId;
|
||||
/**
|
||||
* 原文件名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 路径,即文件名
|
||||
*/
|
||||
private String path;
|
||||
/**
|
||||
* 访问地址
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* 文件的 MIME 类型,例如 "application/octet-stream"
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 文件大小
|
||||
*/
|
||||
private Integer size;
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.job;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.infra.enums.job.JobStatusEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 定时任务 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_job")
|
||||
@KeySequence("infra_job_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class JobDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 任务编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 任务状态
|
||||
*
|
||||
* 枚举 {@link JobStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 处理器的名字
|
||||
*/
|
||||
private String handlerName;
|
||||
/**
|
||||
* 处理器的参数
|
||||
*/
|
||||
private String handlerParam;
|
||||
/**
|
||||
* CRON 表达式
|
||||
*/
|
||||
private String cronExpression;
|
||||
|
||||
// ========== 重试相关字段 ==========
|
||||
/**
|
||||
* 重试次数
|
||||
* 如果不重试,则设置为 0
|
||||
*/
|
||||
private Integer retryCount;
|
||||
/**
|
||||
* 重试间隔,单位:毫秒
|
||||
* 如果没有间隔,则设置为 0
|
||||
*/
|
||||
private Integer retryInterval;
|
||||
|
||||
// ========== 监控相关字段 ==========
|
||||
/**
|
||||
* 监控超时时间,单位:毫秒
|
||||
* 为空时,表示不监控
|
||||
*
|
||||
* 注意,这里的超时的目的,不是进行任务的取消,而是告警任务的执行时间过长
|
||||
*/
|
||||
private Integer monitorTimeout;
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user