Merge branch 'upStreamMaster'

This commit is contained in:
Hobo
2022-04-24 09:43:24 +08:00
1040 changed files with 19552 additions and 10247 deletions

View File

@@ -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 path, byte[] content) throws Exception {
return fileService.createFile(path, content);
}
}

View File

@@ -0,0 +1 @@
package cn.iocoder.yudao.module.infra.api;

View File

@@ -0,0 +1,168 @@
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.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.SchemaTableRespVO;
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.dal.dataobject.codegen.SchemaTableDO;
import cn.iocoder.yudao.module.infra.service.codegen.CodegenService;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
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 java.util.Set;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Api(tags = "管理后台 - 代码生成器")
@RestController
@RequestMapping("/infra/codegen")
@Validated
public class CodegenController {
@Resource
private CodegenService codegenService;
@GetMapping("/db/table/list")
@ApiOperation(value = "获得数据库自带的表定义列表", notes = "会过滤掉已经导入 Codegen 的表")
@ApiImplicitParams({
@ApiImplicitParam(name = "tableName", value = "表名,模糊匹配", required = true, example = "yudao", dataTypeClass = String.class),
@ApiImplicitParam(name = "tableComment", value = "描述,模糊匹配", required = true, example = "芋道", dataTypeClass = String.class)
})
@PreAuthorize("@ss.hasPermission('infra:codegen:query')")
public CommonResult<List<SchemaTableRespVO>> getSchemaTableList(
@RequestParam(value = "tableName", required = false) String tableName,
@RequestParam(value = "tableComment", required = false) String tableComment) {
// 获得数据库自带的表定义列表
List<SchemaTableDO> schemaTables = codegenService.getSchemaTableList(tableName, tableComment);
// 移除在 Codegen 中,已经存在的
Set<String> existsTables = CollectionUtils.convertSet(codegenService.getCodeGenTableList(), CodegenTableDO::getTableName);
schemaTables.removeIf(table -> existsTables.contains(table.getTableName()));
return success(CodegenConvert.INSTANCE.convertList04(schemaTables));
}
@GetMapping("/table/page")
@ApiOperation("获得表定义分页")
@PreAuthorize("@ss.hasPermission('infra:codegen:query')")
public CommonResult<PageResult<CodegenTableRespVO>> getCodeGenTablePage(@Valid CodegenTablePageReqVO pageReqVO) {
PageResult<CodegenTableDO> pageResult = codegenService.getCodegenTablePage(pageReqVO);
return success(CodegenConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/detail")
@ApiOperation("获得表和字段的明细")
@ApiImplicitParam(name = "tableId", value = "表编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('infra:codegen:query')")
public CommonResult<CodegenDetailRespVO> getCodegenDetail(@RequestParam("tableId") Long tableId) {
CodegenTableDO table = codegenService.getCodegenTablePage(tableId);
List<CodegenColumnDO> columns = codegenService.getCodegenColumnListByTableId(tableId);
// 拼装返回
return success(CodegenConvert.INSTANCE.convert(table, columns));
}
@ApiOperation("基于数据库的表结构,创建代码生成器的表和字段定义")
@ApiImplicitParam(name = "tableNames", value = "表名数组", required = true, example = "sys_user", dataTypeClass = List.class)
@PostMapping("/create-list-from-db")
@PreAuthorize("@ss.hasPermission('infra:codegen:create')")
public CommonResult<List<Long>> createCodegenListFromDB(@RequestParam("tableNames") List<String> tableNames) {
return success(codegenService.createCodegenListFromDB(getLoginUserId(), tableNames));
}
@ApiOperation("基于 SQL 建表语句,创建代码生成器的表和字段定义")
@ApiImplicitParam(name = "sql", value = "SQL 建表语句", required = true, example = "sql", dataTypeClass = String.class)
@PostMapping("/create-list-from-sql")
@PreAuthorize("@ss.hasPermission('infra:codegen:create')")
public CommonResult<Long> createCodegenListFromSQL(@RequestParam("sql") String sql) {
return success(codegenService.createCodegenListFromSQL(getLoginUserId(), sql));
}
@ApiOperation("更新数据库的表和字段定义")
@PutMapping("/update")
@PreAuthorize("@ss.hasPermission('infra:codegen:update')")
public CommonResult<Boolean> updateCodegen(@Valid @RequestBody CodegenUpdateReqVO updateReqVO) {
codegenService.updateCodegen(updateReqVO);
return success(true);
}
@ApiOperation("基于数据库的表结构,同步数据库的表和字段定义")
@PutMapping("/sync-from-db")
@ApiImplicitParam(name = "tableId", value = "表编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('infra:codegen:update')")
public CommonResult<Boolean> syncCodegenFromDB(@RequestParam("tableId") Long tableId) {
codegenService.syncCodegenFromDB(tableId);
return success(true);
}
@ApiOperation("基于 SQL 建表语句,同步数据库的表和字段定义")
@PutMapping("/sync-from-sql")
@ApiImplicitParams({
@ApiImplicitParam(name = "tableId", value = "表编号", required = true, example = "1024", dataTypeClass = Long.class),
@ApiImplicitParam(name = "sql", value = "SQL 建表语句", required = true, example = "sql", dataTypeClass = String.class)
})
@PreAuthorize("@ss.hasPermission('infra:codegen:update')")
public CommonResult<Boolean> syncCodegenFromSQL(@RequestParam("tableId") Long tableId,
@RequestParam("sql") String sql) {
codegenService.syncCodegenFromSQL(tableId, sql);
return success(true);
}
@ApiOperation("删除数据库的表和字段定义")
@DeleteMapping("/delete")
@ApiImplicitParam(name = "tableId", value = "表编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('infra:codegen:delete')")
public CommonResult<Boolean> deleteCodegen(@RequestParam("tableId") Long tableId) {
codegenService.deleteCodegen(tableId);
return success(true);
}
@ApiOperation("预览生成代码")
@GetMapping("/preview")
@ApiImplicitParam(name = "tableId", value = "表编号", required = true, example = "1024", dataTypeClass = Long.class)
@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));
}
@ApiOperation("下载生成代码")
@GetMapping("/download")
@ApiImplicitParam(name = "tableId", value = "表编号", required = true, example = "1024", dataTypeClass = Long.class)
@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());
}
}

View File

@@ -0,0 +1,21 @@
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.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@ApiModel("管理后台 - 代码生成表和字段的明细 Response VO")
@Data
public class CodegenDetailRespVO {
@ApiModelProperty("表定义")
private CodegenTableRespVO table;
@ApiModelProperty("字段定义")
private List<CodegenColumnRespVO> columns;
}

View File

@@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(value = "管理后台 - 代码生成预览 Response VO", description ="注意,每个文件都是一个该对象")
@Data
public class CodegenPreviewRespVO {
@ApiModelProperty(value = "文件路径", required = true, example = "java/cn/iocoder/yudao/adminserver/modules/system/controller/test/SysTestDemoController.java")
private String filePath;
@ApiModelProperty(value = "代码", required = true, example = "Hello World")
private String code;
}

View File

@@ -0,0 +1,60 @@
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.column.CodegenColumnBaseVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTableBaseVO;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.Valid;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;
import java.util.List;
@ApiModel("管理后台 - 代码生成表和字段的修改 Request VO")
@Data
public class CodegenUpdateReqVO {
@Valid // 校验内嵌的字段
@NotNull(message = "表定义不能为空")
private Table table;
@Valid // 校验内嵌的字段
@NotNull(message = "字段定义不能为空")
private List<Column> columns;
@ApiModel("更新表定义")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Valid
public static class Table extends CodegenTableBaseVO {
@ApiModelProperty(value = "编号", required = true, example = "1")
private Long id;
@AssertTrue(message = "上级菜单不能为空")
public boolean isParentMenuIdValid() {
// 生成场景为管理后台时,必须设置上级菜单,不然生成的菜单 SQL 是无父级菜单的
return ObjectUtil.notEqual(getScene(), CodegenSceneEnum.ADMIN.getScene())
|| getParentMenuId() != null;
}
}
@ApiModel("更新表定义")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public static class Column extends CodegenColumnBaseVO {
@ApiModelProperty(value = "编号", required = true, example = "1")
private Long id;
}
}

View File

@@ -0,0 +1,85 @@
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.column;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 代码生成字段定义 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class CodegenColumnBaseVO {
@ApiModelProperty(value = "表编号", required = true, example = "1")
@NotNull(message = "表编号不能为空")
private Long tableId;
@ApiModelProperty(value = "字段名", required = true, example = "user_age")
@NotNull(message = "字段名不能为空")
private String columnName;
@ApiModelProperty(value = "字段类型", required = true, example = "int(11)")
@NotNull(message = "字段类型不能为空")
private String columnType;
@ApiModelProperty(value = "字段描述", required = true, example = "年龄")
@NotNull(message = "字段描述不能为空")
private String columnComment;
@ApiModelProperty(value = "是否允许为空", required = true, example = "true")
@NotNull(message = "是否允许为空不能为空")
private Boolean nullable;
@ApiModelProperty(value = "是否主键", required = true, example = "false")
@NotNull(message = "是否主键不能为空")
private Boolean primaryKey;
@ApiModelProperty(value = "是否自增", required = true, example = "true")
@NotNull(message = "是否自增不能为空")
private String autoIncrement;
@ApiModelProperty(value = "排序", required = true, example = "10")
@NotNull(message = "排序不能为空")
private Integer ordinalPosition;
@ApiModelProperty(value = "Java 属性类型", required = true, example = "userAge")
@NotNull(message = "Java 属性类型不能为空")
private String javaType;
@ApiModelProperty(value = "Java 属性名", required = true, example = "Integer")
@NotNull(message = "Java 属性名不能为空")
private String javaField;
@ApiModelProperty(value = "字典类型", example = "sys_gender")
private String dictType;
@ApiModelProperty(value = "数据示例", example = "1024")
private String example;
@ApiModelProperty(value = "是否为 Create 创建操作的字段", required = true, example = "true")
@NotNull(message = "是否为 Create 创建操作的字段不能为空")
private Boolean createOperation;
@ApiModelProperty(value = "是否为 Update 更新操作的字段", required = true, example = "false")
@NotNull(message = "是否为 Update 更新操作的字段不能为空")
private Boolean updateOperation;
@ApiModelProperty(value = "是否为 List 查询操作的字段", required = true, example = "true")
@NotNull(message = "是否为 List 查询操作的字段不能为空")
private Boolean listOperation;
@ApiModelProperty(value = "List 查询操作的条件类型", required = true, example = "LIKE", notes = "参见 CodegenColumnListConditionEnum 枚举")
@NotNull(message = "List 查询操作的条件类型不能为空")
private String listOperationCondition;
@ApiModelProperty(value = "是否为 List 查询操作的返回字段", required = true, example = "true")
@NotNull(message = "是否为 List 查询操作的返回字段不能为空")
private Boolean listOperationResult;
@ApiModelProperty(value = "显示类型", required = true, example = "input")
@NotNull(message = "显示类型不能为空")
private String htmlType;
}

View File

@@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.column;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
@ApiModel("管理后台 - 代码生成字段定义 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CodegenColumnRespVO extends CodegenColumnBaseVO {
@ApiModelProperty(value = "编号", required = true, example = "1")
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@@ -0,0 +1,61 @@
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 代码生成 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class CodegenTableBaseVO {
@ApiModelProperty(value = "导入类型", required = true, example = "1", notes = "参见 CodegenImportTypeEnum 枚举")
@NotNull(message = "导入类型不能为空")
private Integer importType;
@ApiModelProperty(value = "生成场景", required = true, example = "1", notes = "参见 CodegenSceneEnum 枚举")
@NotNull(message = "导入类型不能为空")
private Integer scene;
@ApiModelProperty(value = "表名称", required = true, example = "yudao")
@NotNull(message = "表名称不能为空")
private String tableName;
@ApiModelProperty(value = "表描述", required = true, example = "芋道")
@NotNull(message = "表描述不能为空")
private String tableComment;
@ApiModelProperty(value = "备注", example = "我是备注")
private String remark;
@ApiModelProperty(value = "模块名", required = true, example = "system")
@NotNull(message = "模块名不能为空")
private String moduleName;
@ApiModelProperty(value = "业务名", required = true, example = "codegen")
@NotNull(message = "业务名不能为空")
private String businessName;
@ApiModelProperty(value = "类名称", required = true, example = "CodegenTable")
@NotNull(message = "类名称不能为空")
private String className;
@ApiModelProperty(value = "类描述", required = true, example = "代码生成器的表定义")
@NotNull(message = "类描述不能为空")
private String classComment;
@ApiModelProperty(value = "作者", required = true, example = "芋道源码")
@NotNull(message = "作者不能为空")
private String author;
@ApiModelProperty(value = "模板类型", required = true, example = "1", notes = "参见 CodegenTemplateTypeEnum 枚举")
@NotNull(message = "模板类型不能为空")
private Integer templateType;
@ApiModelProperty(value = "父菜单编号", example = "1024")
private Long parentMenuId;
}

View File

@@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 表定义分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CodegenTablePageReqVO extends PageParam {
@ApiModelProperty(value = "表名称", example = "yudao", notes = "模糊匹配")
private String tableName;
@ApiModelProperty(value = "表描述", example = "芋道", notes = "模糊匹配")
private String tableComment;
@ApiModelProperty(value = "开始创建时间", example = "2020-10-24 00:00:00")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date beginCreateTime;
@ApiModelProperty(value = "结束创建时间", example = "2020-10-24 23:59:59")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date endCreateTime;
}

View File

@@ -0,0 +1,26 @@
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
@ApiModel("管理后台 - 代码生成表定义 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CodegenTableRespVO extends CodegenTableBaseVO {
@ApiModelProperty(value = "编号", required = true, example = "1")
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
@ApiModelProperty(value = "更新时间", required = true)
private Date updateTime;
}

View File

@@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@ApiModel("管理后台 - 数据字典的表定义 Response VO")
@Data
public class SchemaTableRespVO {
@ApiModelProperty(value = "数据库", required = true, example = "yudao")
private String tableSchema;
@ApiModelProperty(value = "表名称", required = true, example = "yuanma")
private String tableName;
@ApiModelProperty(value = "表描述", required = true, example = "芋道源码")
private String tableComment;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@@ -0,0 +1,105 @@
package cn.iocoder.yudao.module.infra.controller.admin.config;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.infra.controller.admin.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.service.config.ConfigService;
import cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
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;
@Api(tags = "管理后台 - 参数配置")
@RestController
@RequestMapping("/infra/config")
@Validated
public class ConfigController {
@Resource
private ConfigService configService;
@PostMapping("/create")
@ApiOperation("创建参数配置")
@PreAuthorize("@ss.hasPermission('infra:config:create')")
public CommonResult<Long> createConfig(@Valid @RequestBody ConfigCreateReqVO reqVO) {
return success(configService.createConfig(reqVO));
}
@PutMapping("/update")
@ApiOperation("修改参数配置")
@PreAuthorize("@ss.hasPermission('infra:config:update')")
public CommonResult<Boolean> updateConfig(@Valid @RequestBody ConfigUpdateReqVO reqVO) {
configService.updateConfig(reqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除参数配置")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('infra:config:delete')")
public CommonResult<Boolean> deleteConfig(@RequestParam("id") Long id) {
configService.deleteConfig(id);
return success(true);
}
@GetMapping(value = "/get")
@ApiOperation("获得参数配置")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@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")
@ApiOperation(value = "根据参数键名查询参数值", notes = "敏感配置,不允许返回给前端")
@ApiImplicitParam(name = "key", value = "参数键", required = true, example = "yunai.biz.username", dataTypeClass = String.class)
public CommonResult<String> getConfigKey(@RequestParam("key") String key) {
ConfigDO config = configService.getConfigByKey(key);
if (config == null) {
return null;
}
if (config.getSensitive()) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_GET_VALUE_ERROR_IF_SENSITIVE);
}
return success(config.getValue());
}
@GetMapping("/page")
@ApiOperation("获取参数配置分页")
@PreAuthorize("@ss.hasPermission('infra:config:query')")
public CommonResult<PageResult<ConfigRespVO>> getConfigPage(@Valid ConfigPageReqVO reqVO) {
PageResult<ConfigDO> page = configService.getConfigPage(reqVO);
return success(ConfigConvert.INSTANCE.convertPage(page));
}
@GetMapping("/export")
@ApiOperation("导出参数配置")
@PreAuthorize("@ss.hasPermission('infra:config:export')")
@OperateLog(type = EXPORT)
public void exportSysConfig(@Valid ConfigExportReqVO reqVO,
HttpServletResponse response) throws IOException {
List<ConfigDO> list = configService.getConfigList(reqVO);
// 拼接数据
List<ConfigExcelVO> datas = ConfigConvert.INSTANCE.convertList(list);
// 输出
ExcelUtils.write(response, "参数配置.xls", "数据", ConfigExcelVO.class, datas);
}
}

View File

@@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.infra.controller.admin.config.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* 参数配置 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class ConfigBaseVO {
@ApiModelProperty(value = "参数分组", required = true, example = "biz")
@NotEmpty(message = "参数分组不能为空")
@Size(max = 50, message = "参数名称不能超过50个字符")
private String group;
@ApiModelProperty(value = "参数名称", required = true, example = "数据库名")
@NotBlank(message = "参数名称不能为空")
@Size(max = 100, message = "参数名称不能超过100个字符")
private String name;
@ApiModelProperty(value = "参数键值", required = true, example = "1024")
@NotBlank(message = "参数键值不能为空")
@Size(max = 500, message = "参数键值长度不能超过500个字符")
private String value;
@ApiModelProperty(value = "是否敏感", required = true, example = "true")
@NotNull(message = "是否敏感不能为空")
private Boolean sensitive;
@ApiModelProperty(value = "备注", example = "备注一下很帅气!")
private String remark;
}

View File

@@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.infra.controller.admin.config.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
@ApiModel("管理后台 - 参数配置创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class ConfigCreateReqVO extends ConfigBaseVO {
@ApiModelProperty(value = "参数键名", required = true, example = "yunai.db.username")
@NotBlank(message = "参数键名长度不能为空")
@Size(max = 100, message = "参数键名长度不能超过100个字符")
private String key;
}

View File

@@ -0,0 +1,46 @@
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.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* 参数配置 Excel 导出响应 VO
*/
@Data
public class ConfigExcelVO {
@ExcelProperty("参数配置序号")
private Long id;
@ExcelProperty("参数键名")
private String key;
@ExcelProperty("参数分组")
private String group;
@ExcelProperty("参数名称")
private String name;
@ExcelProperty("参数键值")
private String value;
@ExcelProperty(value = "参数类型", converter = DictConvert.class)
@DictFormat(DictTypeConstants.CONFIG_TYPE)
private Integer type;
@ExcelProperty(value = "是否敏感", converter = DictConvert.class)
@DictFormat(DictTypeConstants.BOOLEAN_STRING)
private Boolean sensitive;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.infra.controller.admin.config.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 参数配置导出 Request VO")
@Data
public class ConfigExportReqVO {
@ApiModelProperty(value = "参数名称", example = "模糊匹配")
private String name;
@ApiModelProperty(value = "参数键名", example = "yunai.db.username", notes = "模糊匹配")
private String key;
@ApiModelProperty(value = "参数类型", example = "1", notes = "参见 SysConfigTypeEnum 枚举")
private Integer type;
@ApiModelProperty(value = "开始时间", example = "2020-10-24 00:00:00")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date beginTime;
@ApiModelProperty(value = "结束时间", example = "2020-10-24 23:59:59")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date endTime;
}

View File

@@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.infra.controller.admin.config.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 参数配置分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ConfigPageReqVO extends PageParam {
@ApiModelProperty(value = "参数名称", example = "模糊匹配")
private String name;
@ApiModelProperty(value = "参数键名", example = "yunai.db.username", notes = "模糊匹配")
private String key;
@ApiModelProperty(value = "参数类型", example = "1", notes = "参见 SysConfigTypeEnum 枚举")
private Integer type;
@ApiModelProperty(value = "开始时间", example = "2020-10-24 00:00:00")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date beginTime;
@ApiModelProperty(value = "结束时间", example = "2020-10-24 23:59:59")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date endTime;
}

View File

@@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.infra.controller.admin.config.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.util.Date;
@ApiModel("管理后台 - 参数配置信息 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class ConfigRespVO extends ConfigBaseVO {
@ApiModelProperty(value = "参数配置序号", required = true, example = "1024")
private Long id;
@ApiModelProperty(value = "参数键名", required = true, example = "yunai.db.username")
@NotBlank(message = "参数键名长度不能为空")
@Size(max = 100, message = "参数键名长度不能超过100个字符")
private String key;
@ApiModelProperty(value = "参数类型", required = true, example = "1", notes = "参见 SysConfigTypeEnum 枚举")
private Integer type;
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
private Date createTime;
}

View File

@@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.infra.controller.admin.config.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@ApiModel("管理后台 - 参数配置创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ConfigUpdateReqVO extends ConfigBaseVO {
@ApiModelProperty(value = "参数配置序号", required = true, example = "1024")
@NotNull(message = "参数配置编号不能为空")
private Long id;
}

View File

@@ -0,0 +1,157 @@
package cn.iocoder.yudao.module.infra.controller.admin.doc;
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.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
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;
@Api(tags = "管理后台 - 数据库文档")
@RestController
@RequestMapping("/infra/db-doc")
public class DbDocController {
@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")
@ApiOperation("导出 html 格式的数据文档")
@ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true",
dataTypeClass = Boolean.class)
public void exportHtml(@RequestParam(defaultValue = "true") Boolean deleteFile,
HttpServletResponse response) throws IOException {
doExportFile(EngineFileType.HTML, deleteFile, response);
}
@GetMapping("/export-word")
@ApiOperation("导出 word 格式的数据文档")
@ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true",
dataTypeClass = Boolean.class)
public void exportWord(@RequestParam(defaultValue = "true") Boolean deleteFile,
HttpServletResponse response) throws IOException {
doExportFile(EngineFileType.WORD, deleteFile, response);
}
@GetMapping("/export-markdown")
@ApiOperation("导出 markdown 格式的数据文档")
@ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true",
dataTypeClass = Boolean.class)
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_")) // 忽略表前缀
.build();
}
}

View File

@@ -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}}

View File

@@ -0,0 +1,89 @@
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.module.infra.controller.admin.file.vo.config.FileConfigCreateReqVO;
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.FileConfigUpdateReqVO;
import cn.iocoder.yudao.module.infra.convert.file.FileConfigConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
import cn.iocoder.yudao.module.infra.service.file.FileConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
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;
@Api(tags = "管理后台 - 文件配置")
@RestController
@RequestMapping("/infra/file-config")
@Validated
public class FileConfigController {
@Resource
private FileConfigService fileConfigService;
@PostMapping("/create")
@ApiOperation("创建文件配置")
@PreAuthorize("@ss.hasPermission('infra:file-config:create')")
public CommonResult<Long> createFileConfig(@Valid @RequestBody FileConfigCreateReqVO createReqVO) {
return success(fileConfigService.createFileConfig(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新文件配置")
@PreAuthorize("@ss.hasPermission('infra:file-config:update')")
public CommonResult<Boolean> updateFileConfig(@Valid @RequestBody FileConfigUpdateReqVO updateReqVO) {
fileConfigService.updateFileConfig(updateReqVO);
return success(true);
}
@PutMapping("/update-master")
@ApiOperation("更新文件配置为 Master")
@PreAuthorize("@ss.hasPermission('infra:file-config:update')")
public CommonResult<Boolean> updateFileConfigMaster(@RequestParam("id") Long id) {
fileConfigService.updateFileConfigMaster(id);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除文件配置")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('infra:file-config:delete')")
public CommonResult<Boolean> deleteFileConfig(@RequestParam("id") Long id) {
fileConfigService.deleteFileConfig(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得文件配置")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('infra:file-config:query')")
public CommonResult<FileConfigRespVO> getFileConfig(@RequestParam("id") Long id) {
FileConfigDO fileConfig = fileConfigService.getFileConfig(id);
return success(FileConfigConvert.INSTANCE.convert(fileConfig));
}
@GetMapping("/page")
@ApiOperation("获得文件配置分页")
@PreAuthorize("@ss.hasPermission('infra:file-config:query')")
public CommonResult<PageResult<FileConfigRespVO>> getFileConfigPage(@Valid FileConfigPageReqVO pageVO) {
PageResult<FileConfigDO> pageResult = fileConfigService.getFileConfigPage(pageVO);
return success(FileConfigConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/test")
@ApiOperation("测试文件配置是否正确")
@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);
}
}

View File

@@ -0,0 +1,85 @@
package cn.iocoder.yudao.module.infra.controller.admin.file;
import cn.hutool.core.io.IoUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileRespVO;
import cn.iocoder.yudao.module.infra.convert.file.FileConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import cn.iocoder.yudao.module.infra.service.file.FileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
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.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Api(tags = "管理后台 - 文件存储")
@RestController
@RequestMapping("/infra/file")
@Validated
@Slf4j
public class FileController {
@Resource
private FileService fileService;
@PostMapping("/upload")
@ApiOperation("上传文件")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "文件附件", required = true, dataTypeClass = MultipartFile.class),
@ApiImplicitParam(name = "path", value = "文件路径", example = "yudaoyuanma.png", dataTypeClass = String.class)
})
public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file,
@RequestParam("path") String path) throws Exception {
return success(fileService.createFile(path, IoUtil.readBytes(file.getInputStream())));
}
@DeleteMapping("/delete")
@ApiOperation("删除文件")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@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/{path}")
@ApiOperation("下载文件")
@ApiImplicitParams({
@ApiImplicitParam(name = "configId", value = "配置编号", required = true, dataTypeClass = Long.class),
@ApiImplicitParam(name = "path", value = "文件路径", required = true, dataTypeClass = String.class)
})
public void getFileContent(HttpServletResponse response,
@PathVariable("configId") Long configId,
@PathVariable("path") String path) throws Exception {
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")
@ApiOperation("获得文件分页")
@PreAuthorize("@ss.hasPermission('infra:file:query')")
public CommonResult<PageResult<FileRespVO>> getFilePage(@Valid FilePageReqVO pageVO) {
PageResult<FileDO> pageResult = fileService.getFilePage(pageVO);
return success(FileConvert.INSTANCE.convertPage(pageResult));
}
}

View File

@@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.config;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 文件配置 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class FileConfigBaseVO {
@ApiModelProperty(value = "配置名", required = true, example = "S3 - 阿里云")
@NotNull(message = "配置名不能为空")
private String name;
@ApiModelProperty(value = "备注", example = "我是备注")
private String remark;
}

View File

@@ -0,0 +1,26 @@
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.config;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.util.Map;
@ApiModel("管理后台 - 文件配置创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class FileConfigCreateReqVO extends FileConfigBaseVO {
@ApiModelProperty(value = "存储器", required = true, example = "1", notes = "参见 FileStorageEnum 枚举类")
@NotNull(message = "存储器不能为空")
private Integer storage;
@ApiModelProperty(value = "存储配置", required = true, notes = "配置是动态参数,所以使用 Map 接收")
@NotNull(message = "存储配置不能为空")
private Map<String, Object> config;
}

View File

@@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.config;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 文件配置分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class FileConfigPageReqVO extends PageParam {
@ApiModelProperty(value = "配置名", example = "S3 - 阿里云")
private String name;
@ApiModelProperty(value = "存储器", example = "1")
private Integer storage;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.config;
import cn.iocoder.yudao.framework.file.core.client.FileClientConfig;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.util.Date;
@ApiModel("管理后台 - 文件配置 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class FileConfigRespVO extends FileConfigBaseVO {
@ApiModelProperty(value = "编号", required = true, example = "1")
private Long id;
@ApiModelProperty(value = "存储器", required = true, example = "1", notes = "参见 FileStorageEnum 枚举类")
@NotNull(message = "存储器不能为空")
private Integer storage;
@ApiModelProperty(value = "是否为主配置", required = true, example = "true")
@NotNull(message = "是否为主配置不能为空")
private Boolean master;
@ApiModelProperty(value = "存储配置", required = true)
private FileClientConfig config;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@@ -0,0 +1,26 @@
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.config;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.util.Map;
@ApiModel("管理后台 - 文件配置更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class FileConfigUpdateReqVO extends FileConfigBaseVO {
@ApiModelProperty(value = "编号", required = true, example = "1")
@NotNull(message = "编号不能为空")
private Long id;
@ApiModelProperty(value = "存储配置", required = true, notes = "配置是动态参数,所以使用 Map 接收")
@NotNull(message = "存储配置不能为空")
private Map<String, Object> config;
}

View File

@@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 文件分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class FilePageReqVO extends PageParam {
@ApiModelProperty(value = "文件路径", example = "yudao", notes = "模糊匹配")
private String path;
@ApiModelProperty(value = "文件类型", example = "jpg", notes = "模糊匹配")
private String type;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@ApiModel(value = "管理后台 - 文件 Response VO", description = "不返回 content 字段,太大")
@Data
public class FileRespVO {
@ApiModelProperty(value = "文件编号", required = true, example = "1024")
private Long id;
@ApiModelProperty(value = "文件路径", required = true, example = "yudao.jpg")
private String path;
@ApiModelProperty(value = "文件 URL", required = true, example = "https://www.iocoder.cn/yudao.jpg")
private String url;
@ApiModelProperty(value = "文件类型", example = "jpg")
private String type;
@ApiModelProperty(value = "文件大小", example = "2048", required = true)
private Integer size;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@@ -0,0 +1,145 @@
package cn.iocoder.yudao.module.infra.controller.admin.job;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.framework.quartz.core.util.CronUtils;
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.*;
import cn.iocoder.yudao.module.infra.convert.job.JobConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO;
import cn.iocoder.yudao.module.infra.service.job.JobService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
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.util.Collection;
import java.util.Collections;
import java.util.Date;
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;
@Api(tags = "管理后台 - 定时任务")
@RestController
@RequestMapping("/infra/job")
@Validated
public class JobController {
@Resource
private JobService jobService;
@PostMapping("/create")
@ApiOperation("创建定时任务")
@PreAuthorize("@ss.hasPermission('infra:job:create')")
public CommonResult<Long> createJob(@Valid @RequestBody JobCreateReqVO createReqVO)
throws SchedulerException {
return success(jobService.createJob(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新定时任务")
@PreAuthorize("@ss.hasPermission('infra:job:update')")
public CommonResult<Boolean> updateJob(@Valid @RequestBody JobUpdateReqVO updateReqVO)
throws SchedulerException {
jobService.updateJob(updateReqVO);
return success(true);
}
@PutMapping("/update-status")
@ApiOperation("更新定时任务的状态")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class),
@ApiImplicitParam(name = "status", value = "状态", required = true, example = "1", dataTypeClass = Integer.class),
})
@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")
@ApiOperation("删除定时任务")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('infra:job:delete')")
public CommonResult<Boolean> deleteJob(@RequestParam("id") Long id)
throws SchedulerException {
jobService.deleteJob(id);
return success(true);
}
@PutMapping("/trigger")
@ApiOperation("触发定时任务")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('infra:job:trigger')")
public CommonResult<Boolean> triggerJob(@RequestParam("id") Long id) throws SchedulerException {
jobService.triggerJob(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得定时任务")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('infra:job:query')")
public CommonResult<JobRespVO> getJob(@RequestParam("id") Long id) {
JobDO job = jobService.getJob(id);
return success(JobConvert.INSTANCE.convert(job));
}
@GetMapping("/list")
@ApiOperation("获得定时任务列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('infra:job:query')")
public CommonResult<List<JobRespVO>> getJobList(@RequestParam("ids") Collection<Long> ids) {
List<JobDO> list = jobService.getJobList(ids);
return success(JobConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得定时任务分页")
@PreAuthorize("@ss.hasPermission('infra:job:query')")
public CommonResult<PageResult<JobRespVO>> getJobPage(@Valid JobPageReqVO pageVO) {
PageResult<JobDO> pageResult = jobService.getJobPage(pageVO);
return success(JobConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@ApiOperation("导出定时任务 Excel")
@PreAuthorize("@ss.hasPermission('infra:job:export')")
@OperateLog(type = EXPORT)
public void exportJobExcel(@Valid JobExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<JobDO> list = jobService.getJobList(exportReqVO);
// 导出 Excel
List<JobExcelVO> datas = JobConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "定时任务.xls", "数据", JobExcelVO.class, datas);
}
@GetMapping("/get_next_times")
@ApiOperation("获得定时任务的下 n 次执行时间")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class),
@ApiImplicitParam(name = "count", value = "数量", example = "5", dataTypeClass = Long.class)
})
@PreAuthorize("@ss.hasPermission('infra:job:query')")
public CommonResult<List<Date>> 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));
}
}

View File

@@ -0,0 +1,81 @@
package cn.iocoder.yudao.module.infra.controller.admin.job;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExcelVO;
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExportReqVO;
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.convert.job.JobLogConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobLogDO;
import cn.iocoder.yudao.module.infra.service.job.JobLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
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.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Api(tags = "管理后台 - 定时任务日志")
@RestController
@RequestMapping("/infra/job-log")
@Validated
public class JobLogController {
@Resource
private JobLogService jobLogService;
@GetMapping("/get")
@ApiOperation("获得定时任务日志")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('infra:job:query')")
public CommonResult<JobLogRespVO> getJobLog(@RequestParam("id") Long id) {
JobLogDO jobLog = jobLogService.getJobLog(id);
return success(JobLogConvert.INSTANCE.convert(jobLog));
}
@GetMapping("/list")
@ApiOperation("获得定时任务日志列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('infra:job:query')")
public CommonResult<List<JobLogRespVO>> getJobLogList(@RequestParam("ids") Collection<Long> ids) {
List<JobLogDO> list = jobLogService.getJobLogList(ids);
return success(JobLogConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得定时任务日志分页")
@PreAuthorize("@ss.hasPermission('infra:job:query')")
public CommonResult<PageResult<JobLogRespVO>> getJobLogPage(@Valid JobLogPageReqVO pageVO) {
PageResult<JobLogDO> pageResult = jobLogService.getJobLogPage(pageVO);
return success(JobLogConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@ApiOperation("导出定时任务日志 Excel")
@PreAuthorize("@ss.hasPermission('infra:job:export')")
@OperateLog(type = EXPORT)
public void exportJobLogExcel(@Valid JobLogExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<JobLogDO> list = jobLogService.getJobLogList(exportReqVO);
// 导出 Excel
List<JobLogExcelVO> datas = JobLogConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "任务日志.xls", "数据", JobLogExcelVO.class, datas);
}
}

View File

@@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 定时任务 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class JobBaseVO {
@ApiModelProperty(value = "任务名称", required = true, example = "测试任务")
@NotNull(message = "任务名称不能为空")
private String name;
@ApiModelProperty(value = "处理器的参数", example = "yudao")
private String handlerParam;
@ApiModelProperty(value = "CRON 表达式", required = true, example = "0/10 * * * * ? *")
@NotNull(message = "CRON 表达式不能为空")
private String cronExpression;
@ApiModelProperty(value = "重试次数", required = true, example = "3")
@NotNull(message = "重试次数不能为空")
private Integer retryCount;
@ApiModelProperty(value = "重试间隔", required = true, example = "1000")
@NotNull(message = "重试间隔不能为空")
private Integer retryInterval;
@ApiModelProperty(value = "监控超时时间", example = "1000")
private Integer monitorTimeout;
}

View File

@@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@ApiModel("管理后台 - 定时任务创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class JobCreateReqVO extends JobBaseVO {
@ApiModelProperty(value = "处理器的名字", required = true, example = "sysUserSessionTimeoutJob")
@NotNull(message = "处理器的名字不能为空")
private String handlerName;
}

View File

@@ -0,0 +1,56 @@
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.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* 定时任务 Excel VO
*
* @author 芋道源码
*/
@Data
public class JobExcelVO {
@ExcelProperty("任务编号")
private Long id;
@ExcelProperty("任务名称")
private String name;
@ExcelProperty(value = "任务状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.JOB_STATUS)
private Integer status;
@ExcelProperty("处理器的名字")
private String handlerName;
@ExcelProperty("处理器的参数")
private String handlerParam;
@ExcelProperty("CRON 表达式")
private String cronExpression;
@ExcelProperty("最后一次执行的开始时间")
private Date executeBeginTime;
@ExcelProperty("最后一次执行的结束时间")
private Date executeEndTime;
@ExcelProperty("上一次触发时间")
private Date firePrevTime;
@ExcelProperty("下一次触发时间")
private Date fireNextTime;
@ExcelProperty("监控超时时间")
private Integer monitorTimeout;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(value = "管理后台 - 定时任务 Excel 导出 Request VO", description = "参数和 JobPageReqVO 是一致的")
@Data
public class JobExportReqVO {
@ApiModelProperty(value = "任务名称", example = "测试任务", notes = "模糊匹配")
private String name;
@ApiModelProperty(value = "任务状态", example = "1", notes = "参见 JobStatusEnum 枚举")
private Integer status;
@ApiModelProperty(value = "处理器的名字", example = "UserSessionTimeoutJob", notes = "模糊匹配")
private String handlerName;
}

View File

@@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ApiModel("管理后台 - 定时任务分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class JobPageReqVO extends PageParam {
@ApiModelProperty(value = "任务名称", example = "测试任务", notes = "模糊匹配")
private String name;
@ApiModelProperty(value = "任务状态", example = "1", notes = "参见 JobStatusEnum 枚举")
private Integer status;
@ApiModelProperty(value = "处理器的名字", example = "sysUserSessionTimeoutJob", notes = "模糊匹配")
private String handlerName;
}

View File

@@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.util.Date;
@ApiModel("管理后台 - 定时任务 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class JobRespVO extends JobBaseVO {
@ApiModelProperty(value = "任务编号", required = true, example = "1024")
private Long id;
@ApiModelProperty(value = "任务状态", required = true, example = "1")
private Integer status;
@ApiModelProperty(value = "处理器的名字", required = true, example = "sysUserSessionTimeoutJob")
@NotNull(message = "处理器的名字不能为空")
private String handlerName;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@ApiModel("管理后台 - 定时任务更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class JobUpdateReqVO extends JobBaseVO {
@ApiModelProperty(value = "任务编号", required = true, example = "1024")
@NotNull(message = "任务编号不能为空")
private Long id;
}

View File

@@ -0,0 +1,53 @@
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 定时任务日志 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class JobLogBaseVO {
@ApiModelProperty(value = "任务编号", required = true, example = "1024")
@NotNull(message = "任务编号不能为空")
private Long jobId;
@ApiModelProperty(value = "处理器的名字", required = true, example = "sysUserSessionTimeoutJob")
@NotNull(message = "处理器的名字不能为空")
private String handlerName;
@ApiModelProperty(value = "处理器的参数", example = "yudao")
private String handlerParam;
@ApiModelProperty(value = "第几次执行", required = true, example = "1")
@NotNull(message = "第几次执行不能为空")
private Integer executeIndex;
@ApiModelProperty(value = "开始执行时间", required = true)
@NotNull(message = "开始执行时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date beginTime;
@ApiModelProperty(value = "结束执行时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date endTime;
@ApiModelProperty(value = "执行时长", example = "123")
private Integer duration;
@ApiModelProperty(value = "任务状态", required = true, example = "1", notes = "参见 JobLogStatusEnum 枚举")
@NotNull(message = "任务状态不能为空")
private Integer status;
@ApiModelProperty(value = "结果数据", example = "执行成功")
private String result;
}

View File

@@ -0,0 +1,53 @@
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.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* 定时任务 Excel VO
*
* @author 芋艿
*/
@Data
public class JobLogExcelVO {
@ExcelProperty("日志编号")
private Long id;
@ExcelProperty("任务编号")
private Long jobId;
@ExcelProperty("处理器的名字")
private String handlerName;
@ExcelProperty("处理器的参数")
private String handlerParam;
@ExcelProperty("第几次执行")
private Integer executeIndex;
@ExcelProperty("开始执行时间")
private Date beginTime;
@ExcelProperty("结束执行时间")
private Date endTime;
@ExcelProperty("执行时长")
private Integer duration;
@ExcelProperty(value = "任务状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.JOB_STATUS)
private Integer status;
@ExcelProperty("结果数据")
private String result;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "管理后台 - 定时任务 Excel 导出 Request VO", description = "参数和 JobLogPageReqVO 是一致的")
@Data
public class JobLogExportReqVO {
@ApiModelProperty(value = "任务编号", example = "10")
private Long jobId;
@ApiModelProperty(value = "处理器的名字", notes = "模糊匹配")
private String handlerName;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始执行时间")
private Date beginTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束执行时间")
private Date endTime;
@ApiModelProperty(value = "任务状态", notes = "参见 JobLogStatusEnum 枚举")
private Integer status;
}

View File

@@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 定时任务日志分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class JobLogPageReqVO extends PageParam {
@ApiModelProperty(value = "任务编号", example = "10")
private Long jobId;
@ApiModelProperty(value = "处理器的名字", notes = "模糊匹配")
private String handlerName;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始执行时间")
private Date beginTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束执行时间")
private Date endTime;
@ApiModelProperty(value = "任务状态", notes = "参见 JobLogStatusEnum 枚举")
private Integer status;
}

View File

@@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
@ApiModel("管理后台 - 定时任务日志 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class JobLogRespVO extends JobLogBaseVO {
@ApiModelProperty(value = "日志编号", required = true, example = "1024")
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@@ -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.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.logger.vo.apiaccesslog.ApiAccessLogExcelVO;
import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExportReqVO;
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.convert.logger.ApiAccessLogConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO;
import cn.iocoder.yudao.module.infra.service.logger.ApiAccessLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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;
@Api(tags = "管理后台 - API 访问日志")
@RestController
@RequestMapping("/infra/api-access-log")
@Validated
public class ApiAccessLogController {
@Resource
private ApiAccessLogService apiAccessLogService;
@GetMapping("/page")
@ApiOperation("获得API 访问日志分页")
@PreAuthorize("@ss.hasPermission('infra:api-access-log:query')")
public CommonResult<PageResult<ApiAccessLogRespVO>> getApiAccessLogPage(@Valid ApiAccessLogPageReqVO pageVO) {
PageResult<ApiAccessLogDO> pageResult = apiAccessLogService.getApiAccessLogPage(pageVO);
return success(ApiAccessLogConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@ApiOperation("导出API 访问日志 Excel")
@PreAuthorize("@ss.hasPermission('infra:api-access-log:export')")
@OperateLog(type = EXPORT)
public void exportApiAccessLogExcel(@Valid ApiAccessLogExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<ApiAccessLogDO> list = apiAccessLogService.getApiAccessLogList(exportReqVO);
// 导出 Excel
List<ApiAccessLogExcelVO> datas = ApiAccessLogConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "API 访问日志.xls", "数据", ApiAccessLogExcelVO.class, datas);
}
}

View File

@@ -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.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.logger.vo.apierrorlog.ApiErrorLogExcelVO;
import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExportReqVO;
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.convert.logger.ApiErrorLogConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO;
import cn.iocoder.yudao.module.infra.service.logger.ApiErrorLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
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;
@Api(tags = "管理后台 - API 错误日志")
@RestController
@RequestMapping("/infra/api-error-log")
@Validated
public class ApiErrorLogController {
@Resource
private ApiErrorLogService apiErrorLogService;
@PutMapping("/update-status")
@ApiOperation("更新 API 错误日志的状态")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class),
@ApiImplicitParam(name = "processStatus", value = "处理状态", required = true, example = "1", dataTypeClass = Integer.class)
})
@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")
@ApiOperation("获得 API 错误日志分页")
@PreAuthorize("@ss.hasPermission('infra:api-error-log:query')")
public CommonResult<PageResult<ApiErrorLogRespVO>> getApiErrorLogPage(@Valid ApiErrorLogPageReqVO pageVO) {
PageResult<ApiErrorLogDO> pageResult = apiErrorLogService.getApiErrorLogPage(pageVO);
return success(ApiErrorLogConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@ApiOperation("导出 API 错误日志 Excel")
@PreAuthorize("@ss.hasPermission('infra:api-error-log:export')")
@OperateLog(type = EXPORT)
public void exportApiErrorLogExcel(@Valid ApiErrorLogExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<ApiErrorLogDO> list = apiErrorLogService.getApiErrorLogList(exportReqVO);
// 导出 Excel
List<ApiErrorLogExcelVO> datas = ApiErrorLogConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "API 错误日志.xls", "数据", ApiErrorLogExcelVO.class, datas);
}
}

View File

@@ -0,0 +1,75 @@
package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* API 访问日志 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class ApiAccessLogBaseVO {
@ApiModelProperty(value = "链路追踪编号", required = true, example = "66600cb6-7852-11eb-9439-0242ac130002")
@NotNull(message = "链路追踪编号不能为空")
private String traceId;
@ApiModelProperty(value = "用户编号", required = true, example = "666")
@NotNull(message = "用户编号不能为空")
private Long userId;
@ApiModelProperty(value = "用户类型", required = true, example = "2", notes = "参见 UserTypeEnum 枚举")
@NotNull(message = "用户类型不能为空")
private Integer userType;
@ApiModelProperty(value = "应用名", required = true, example = "dashboard")
@NotNull(message = "应用名不能为空")
private String applicationName;
@ApiModelProperty(value = "请求方法名", required = true, example = "GET")
@NotNull(message = "请求方法名不能为空")
private String requestMethod;
@ApiModelProperty(value = "请求地址", required = true, example = "/xxx/yyy")
@NotNull(message = "请求地址不能为空")
private String requestUrl;
@ApiModelProperty(value = "请求参数")
private String requestParams;
@ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1")
@NotNull(message = "用户 IP不能为空")
private String userIp;
@ApiModelProperty(value = "浏览器 UA", required = true, example = "Mozilla/5.0")
@NotNull(message = "浏览器 UA不能为空")
private String userAgent;
@ApiModelProperty(value = "开始请求时间", required = true)
@NotNull(message = "开始请求时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date beginTime;
@ApiModelProperty(value = "结束请求时间", required = true)
@NotNull(message = "结束请求时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date endTime;
@ApiModelProperty(value = "执行时长", required = true, example = "100")
@NotNull(message = "执行时长不能为空")
private Integer duration;
@ApiModelProperty(value = "结果码", required = true, example = "0")
@NotNull(message = "结果码不能为空")
private Integer resultCode;
@ApiModelProperty(value = "结果提示", example = "芋道源码,牛逼!")
private String resultMsg;
}

View File

@@ -0,0 +1,65 @@
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.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* API 访问日志 Excel VO
*
* @author 芋道源码
*/
@Data
public class ApiAccessLogExcelVO {
@ExcelProperty("日志主键")
private Long id;
@ExcelProperty("链路追踪编号")
private String traceId;
@ExcelProperty("用户编号")
private Long userId;
@ExcelProperty(value = "用户类型", converter = DictConvert.class)
@DictFormat(DictTypeConstants.USER_TYPE)
private Integer userType;
@ExcelProperty("应用名")
private String applicationName;
@ExcelProperty("请求方法名")
private String requestMethod;
@ExcelProperty("请求地址")
private String requestUrl;
@ExcelProperty("请求参数")
private String requestParams;
@ExcelProperty("用户 IP")
private String userIp;
@ExcelProperty("浏览器 UA")
private String userAgent;
@ExcelProperty("开始请求时间")
private Date beginTime;
@ExcelProperty("结束请求时间")
private Date endTime;
@ExcelProperty("执行时长")
private Integer duration;
@ExcelProperty("结果码")
private Integer resultCode;
@ExcelProperty("结果提示")
private String resultMsg;
}

View File

@@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "管理后台 - API 访问日志 Excel 导出 Request VO", description = "参数和 ApiAccessLogPageReqVO 是一致的")
@Data
public class ApiAccessLogExportReqVO {
@ApiModelProperty(value = "用户编号", example = "666")
private Long userId;
@ApiModelProperty(value = "用户类型", example = "2")
private Integer userType;
@ApiModelProperty(value = "应用名", example = "dashboard")
private String applicationName;
@ApiModelProperty(value = "请求地址", example = "/xxx/yyy", notes = "模糊匹配")
private String requestUrl;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始开始请求时间")
private Date beginBeginTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束开始请求时间")
private Date endBeginTime;
@ApiModelProperty(value = "执行时长", example = "100", notes = "大于等于,单位:毫秒")
private Integer duration;
@ApiModelProperty(value = "结果码", example = "0")
private Integer resultCode;
}

View File

@@ -0,0 +1,47 @@
package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - API 访问日志分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ApiAccessLogPageReqVO extends PageParam {
@ApiModelProperty(value = "用户编号", example = "666")
private Long userId;
@ApiModelProperty(value = "用户类型", example = "2")
private Integer userType;
@ApiModelProperty(value = "应用名", example = "dashboard")
private String applicationName;
@ApiModelProperty(value = "请求地址", example = "/xxx/yyy", notes = "模糊匹配")
private String requestUrl;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始开始请求时间")
private Date beginBeginTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束开始请求时间")
private Date endBeginTime;
@ApiModelProperty(value = "执行时长", example = "100", notes = "大于等于,单位:毫秒")
private Integer duration;
@ApiModelProperty(value = "结果码", example = "0")
private Integer resultCode;
}

View File

@@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
@ApiModel("管理后台 - API 访问日志 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ApiAccessLogRespVO extends ApiAccessLogBaseVO {
@ApiModelProperty(value = "日志主键", required = true, example = "1024")
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@@ -0,0 +1,96 @@
package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* API 错误日志 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class ApiErrorLogBaseVO {
@ApiModelProperty(value = "链路追踪编号", required = true, example = "66600cb6-7852-11eb-9439-0242ac130002")
@NotNull(message = "链路追踪编号不能为空")
private String traceId;
@ApiModelProperty(value = "用户编号", required = true, example = "666")
@NotNull(message = "用户编号不能为空")
private Integer userId;
@ApiModelProperty(value = "用户类型", required = true, example = "1")
@NotNull(message = "用户类型不能为空")
private Integer userType;
@ApiModelProperty(value = "应用名", required = true, example = "dashboard")
@NotNull(message = "应用名不能为空")
private String applicationName;
@ApiModelProperty(value = "请求方法名", required = true, example = "GET")
@NotNull(message = "请求方法名不能为空")
private String requestMethod;
@ApiModelProperty(value = "请求地址", required = true, example = "/xx/yy")
@NotNull(message = "请求地址不能为空")
private String requestUrl;
@ApiModelProperty(value = "请求参数", required = true)
@NotNull(message = "请求参数不能为空")
private String requestParams;
@ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1")
@NotNull(message = "用户 IP不能为空")
private String userIp;
@ApiModelProperty(value = "浏览器 UA", required = true, example = "Mozilla/5.0")
@NotNull(message = "浏览器 UA不能为空")
private String userAgent;
@ApiModelProperty(value = "异常发生时间", required = true)
@NotNull(message = "异常发生时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date exceptionTime;
@ApiModelProperty(value = "异常名", required = true)
@NotNull(message = "异常名不能为空")
private String exceptionName;
@ApiModelProperty(value = "异常导致的消息", required = true)
@NotNull(message = "异常导致的消息不能为空")
private String exceptionMessage;
@ApiModelProperty(value = "异常导致的根消息", required = true)
@NotNull(message = "异常导致的根消息不能为空")
private String exceptionRootCauseMessage;
@ApiModelProperty(value = "异常的栈轨迹", required = true)
@NotNull(message = "异常的栈轨迹不能为空")
private String exceptionStackTrace;
@ApiModelProperty(value = "异常发生的类全名", required = true)
@NotNull(message = "异常发生的类全名不能为空")
private String exceptionClassName;
@ApiModelProperty(value = "异常发生的类文件", required = true)
@NotNull(message = "异常发生的类文件不能为空")
private String exceptionFileName;
@ApiModelProperty(value = "异常发生的方法名", required = true)
@NotNull(message = "异常发生的方法名不能为空")
private String exceptionMethodName;
@ApiModelProperty(value = "异常发生的方法所在行", required = true)
@NotNull(message = "异常发生的方法所在行不能为空")
private Integer exceptionLineNumber;
@ApiModelProperty(value = "处理状态", required = true, example = "0")
@NotNull(message = "处理状态不能为空")
private Integer processStatus;
}

View File

@@ -0,0 +1,90 @@
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.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* API 错误日志 Excel VO
*
* @author 芋道源码
*/
@Data
public class ApiErrorLogExcelVO {
@ExcelProperty("编号")
private Integer id;
@ExcelProperty("链路追踪编号")
private String traceId;
@ExcelProperty("用户编号")
private Integer userId;
@ExcelProperty(value = "用户类型", converter = DictConvert.class)
@DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_TYPE)
private Integer userType;
@ExcelProperty("应用名")
private String applicationName;
@ExcelProperty("请求方法名")
private String requestMethod;
@ExcelProperty("请求地址")
private String requestUrl;
@ExcelProperty("请求参数")
private String requestParams;
@ExcelProperty("用户 IP")
private String userIp;
@ExcelProperty("浏览器 UA")
private String userAgent;
@ExcelProperty("异常发生时间")
private Date exceptionTime;
@ExcelProperty("异常名")
private String exceptionName;
@ExcelProperty("异常导致的消息")
private String exceptionMessage;
@ExcelProperty("异常导致的根消息")
private String exceptionRootCauseMessage;
@ExcelProperty("异常的栈轨迹")
private String exceptionStackTrace;
@ExcelProperty("异常发生的类全名")
private String exceptionClassName;
@ExcelProperty("异常发生的类文件")
private String exceptionFileName;
@ExcelProperty("异常发生的方法名")
private String exceptionMethodName;
@ExcelProperty("异常发生的方法所在行")
private Integer exceptionLineNumber;
@ExcelProperty("创建时间")
private Date createTime;
@ExcelProperty(value = "处理状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.API_ERROR_LOG_PROCESS_STATUS)
private Integer processStatus;
@ExcelProperty("处理时间")
private Date processTime;
@ExcelProperty("处理用户编号")
private Integer processUserId;
}

View File

@@ -0,0 +1,39 @@
package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "管理后台 - API 错误日志 Excel 导出 Request VO", description = "参数和 ApiErrorLogPageReqVO 是一致的")
@Data
public class ApiErrorLogExportReqVO {
@ApiModelProperty(value = "用户编号", example = "666")
private Long userId;
@ApiModelProperty(value = "用户类型", example = "1")
private Integer userType;
@ApiModelProperty(value = "应用名", example = "dashboard")
private String applicationName;
@ApiModelProperty(value = "请求地址", example = "/xx/yy")
private String requestUrl;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始异常发生时间")
private Date beginExceptionTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束异常发生时间")
private Date endExceptionTime;
@ApiModelProperty(value = "处理状态", example = "0")
private Integer processStatus;
}

View File

@@ -0,0 +1,44 @@
package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - API 错误日志分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ApiErrorLogPageReqVO extends PageParam {
@ApiModelProperty(value = "用户编号", example = "666")
private Long userId;
@ApiModelProperty(value = "用户类型", example = "1")
private Integer userType;
@ApiModelProperty(value = "应用名", example = "dashboard")
private String applicationName;
@ApiModelProperty(value = "请求地址", example = "/xx/yy")
private String requestUrl;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始异常发生时间")
private Date beginExceptionTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束异常发生时间")
private Date endExceptionTime;
@ApiModelProperty(value = "处理状态", example = "0")
private Integer processStatus;
}

View File

@@ -0,0 +1,29 @@
package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
@ApiModel("管理后台 - API 错误日志 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ApiErrorLogRespVO extends ApiErrorLogBaseVO {
@ApiModelProperty(value = "编号", required = true, example = "1024")
private Integer id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
@ApiModelProperty(value = "处理时间", required = true)
private Date processTime;
@ApiModelProperty(value = "处理用户编号", example = "233")
private Integer processUserId;
}

View File

@@ -0,0 +1,9 @@
### 请求 /infra/redis/get-monitor-info 接口 => 成功
GET {{baseUrl}}/infra/redis/get-monitor-info
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
### 请求 /infra/redis/get-key-list 接口 => 成功
GET {{baseUrl}}/infra/redis/get-key-list
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}

View File

@@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.infra.controller.admin.redis;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
import cn.iocoder.yudao.framework.redis.core.RedisKeyRegistry;
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO;
import cn.iocoder.yudao.module.infra.convert.redis.RedisConvert;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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.List;
import java.util.Properties;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Api(tags = "管理后台 - Redis 监控")
@RestController
@RequestMapping("/infra/redis")
public class RedisController {
@Resource
private StringRedisTemplate stringRedisTemplate;
@GetMapping("/get-monitor-info")
@ApiOperation("获得 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));
}
@GetMapping("/get-key-list")
@ApiOperation("获得 Redis Key 列表")
@PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
public CommonResult<List<RedisKeyRespVO>> getKeyList() {
List<RedisKeyDefine> keyDefines = RedisKeyRegistry.list();
return success(RedisConvert.INSTANCE.convertList(keyDefines));
}
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.infra.controller.admin.redis.vo;
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import java.time.Duration;
@ApiModel("管理后台 - Redis Key 信息 Response VO")
@Data
@Builder
@AllArgsConstructor
public class RedisKeyRespVO {
@ApiModelProperty(value = "login_user:%s", required = true, example = "String")
private String keyTemplate;
@ApiModelProperty(value = "Key 类型的枚举", required = true, example = "String")
private RedisKeyDefine.KeyTypeEnum keyType;
@ApiModelProperty(value = "Value 类型", required = true, example = "java.lang.String")
private Class<?> valueType;
@ApiModelProperty(value = "超时类型", required = true, example = "1")
private RedisKeyDefine.TimeoutTypeEnum timeoutType;
@ApiModelProperty(value = "过期时间,单位:毫秒", required = true, example = "1024")
private Duration timeout;
@ApiModelProperty(value = "备注", required = true, example = "啦啦啦啦~")
private String memo;
}

View File

@@ -0,0 +1,44 @@
package cn.iocoder.yudao.module.infra.controller.admin.redis.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import java.util.List;
import java.util.Properties;
@ApiModel("管理后台 - Redis 监控信息 Response VO")
@Data
@Builder
@AllArgsConstructor
public class RedisMonitorRespVO {
@ApiModelProperty(value = "Redis info 指令结果", required = true, notes = "具体字段,查看 Redis 文档")
private Properties info;
@ApiModelProperty(value = "Redis key 数量", required = true, example = "1024")
private Long dbSize;
@ApiModelProperty(value = "CommandStat 数组", required = true)
private List<CommandStat> commandStats;
@ApiModel("Redis 命令统计结果")
@Data
@Builder
@AllArgsConstructor
public static class CommandStat {
@ApiModelProperty(value = "Redis 命令", required = true, example = "get")
private String command;
@ApiModelProperty(value = "调用次数", required = true, example = "1024")
private Integer calls;
@ApiModelProperty(value = "消耗 CPU 秒数", required = true, example = "666")
private Long usec;
}
}

View File

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

View File

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

View File

@@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.infra.controller.admin.test.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* 字典类型 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class TestDemoBaseVO {
@ApiModelProperty(value = "名字", required = true)
@NotNull(message = "名字不能为空")
private String name;
@ApiModelProperty(value = "状态", required = true)
@NotNull(message = "状态不能为空")
private Integer status;
@ApiModelProperty(value = "类型", required = true)
@NotNull(message = "类型不能为空")
private Integer type;
@ApiModelProperty(value = "分类", required = true)
@NotNull(message = "分类不能为空")
private Integer category;
@ApiModelProperty(value = "备注")
private String remark;
}

View File

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

View File

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

View File

@@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.infra.controller.admin.test.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "管理后台 - 字典类型 Excel 导出 Request VO", description = "参数和 TestDemoPageReqVO 是一致的")
@Data
public class TestDemoExportReqVO {
@ApiModelProperty(value = "名字")
private String name;
@ApiModelProperty(value = "状态")
private Integer status;
@ApiModelProperty(value = "类型")
private Integer type;
@ApiModelProperty(value = "分类")
private Integer category;
@ApiModelProperty(value = "备注")
private String remark;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.infra.controller.admin.test.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 字典类型分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TestDemoPageReqVO extends PageParam {
@ApiModelProperty(value = "名字")
private String name;
@ApiModelProperty(value = "状态")
private Integer status;
@ApiModelProperty(value = "类型")
private Integer type;
@ApiModelProperty(value = "分类")
private Integer category;
@ApiModelProperty(value = "备注")
private String remark;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.infra.controller.admin.test.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 字典类型 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TestDemoRespVO extends TestDemoBaseVO {
@ApiModelProperty(value = "编号", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

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

View File

@@ -0,0 +1,4 @@
/**
* 占位
*/
package cn.iocoder.yudao.module.infra.controller.app;

View File

@@ -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;

View File

@@ -0,0 +1,70 @@
package cn.iocoder.yudao.module.infra.convert.codegen;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
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.column.CodegenColumnRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTableRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.SchemaTableRespVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Mapper
public interface CodegenConvert {
CodegenConvert INSTANCE = Mappers.getMapper(CodegenConvert.class);
// ========== InformationSchemaTableDO 和 InformationSchemaColumnDO 相关 ==========
CodegenTableDO convert(SchemaTableDO bean);
List<CodegenColumnDO> convertList(List<SchemaColumnDO> list);
CodegenTableRespVO convert(SchemaColumnDO bean);
// ========== CodegenTableDO 相关 ==========
// List<CodegenTableRespVO> convertList02(List<CodegenTableDO> list);
CodegenTableRespVO convert(CodegenTableDO bean);
PageResult<CodegenTableRespVO> convertPage(PageResult<CodegenTableDO> page);
// ========== CodegenTableDO 相关 ==========
List<CodegenColumnRespVO> convertList02(List<CodegenColumnDO> list);
CodegenTableDO convert(CodegenUpdateReqVO.Table bean);
List<CodegenColumnDO> convertList03(List<CodegenUpdateReqVO.Column> columns);
List<SchemaTableRespVO> convertList04(List<SchemaTableDO> list);
// ========== 其它 ==========
default CodegenDetailRespVO convert(CodegenTableDO table, List<CodegenColumnDO> columns) {
CodegenDetailRespVO respVO = new CodegenDetailRespVO();
respVO.setTable(convert(table));
respVO.setColumns(convertList02(columns));
return respVO;
}
default List<CodegenPreviewRespVO> convert(Map<String, String> codes) {
return codes.entrySet().stream().map(entry -> {
CodegenPreviewRespVO respVO = new CodegenPreviewRespVO();
respVO.setFilePath(entry.getKey());
respVO.setCode(entry.getValue());
return respVO;
}).collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,29 @@
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.ConfigCreateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigExcelVO;
import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigUpdateReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO;
import org.mapstruct.Mapper;
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);
ConfigRespVO convert(ConfigDO bean);
ConfigDO convert(ConfigCreateReqVO bean);
ConfigDO convert(ConfigUpdateReqVO bean);
List<ConfigExcelVO> convertList(List<ConfigDO> list);
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.infra.convert.file;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigCreateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigUpdateReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 文件配置 Convert
*
* @author 芋道源码
*/
@Mapper
public interface FileConfigConvert {
FileConfigConvert INSTANCE = Mappers.getMapper(FileConfigConvert.class);
@Mapping(target = "config", ignore = true)
FileConfigDO convert(FileConfigCreateReqVO bean);
@Mapping(target = "config", ignore = true)
FileConfigDO convert(FileConfigUpdateReqVO bean);
FileConfigRespVO convert(FileConfigDO bean);
List<FileConfigRespVO> convertList(List<FileConfigDO> list);
PageResult<FileConfigRespVO> convertPage(PageResult<FileConfigDO> page);
}

View File

@@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.infra.convert.file;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileRespVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface FileConvert {
FileConvert INSTANCE = Mappers.getMapper(FileConvert.class);
FileRespVO convert(FileDO bean);
PageResult<FileRespVO> convertPage(PageResult<FileDO> page);
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.infra.convert.job;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobCreateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobExcelVO;
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobUpdateReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 定时任务 Convert
*
* @author 芋道源码
*/
@Mapper
public interface JobConvert {
JobConvert INSTANCE = Mappers.getMapper(JobConvert.class);
JobDO convert(JobCreateReqVO bean);
JobDO convert(JobUpdateReqVO bean);
JobRespVO convert(JobDO bean);
List<JobRespVO> convertList(List<JobDO> list);
PageResult<JobRespVO> convertPage(PageResult<JobDO> page);
List<JobExcelVO> convertList02(List<JobDO> list);
}

View File

@@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.infra.convert.job;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExcelVO;
import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogRespVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobLogDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 定时任务日志 Convert
*
* @author 芋艿
*/
@Mapper
public interface JobLogConvert {
JobLogConvert INSTANCE = Mappers.getMapper(JobLogConvert.class);
JobLogRespVO convert(JobLogDO bean);
List<JobLogRespVO> convertList(List<JobLogDO> list);
PageResult<JobLogRespVO> convertPage(PageResult<JobLogDO> page);
List<JobLogExcelVO> convertList02(List<JobLogDO> list);
}

View File

@@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.infra.convert.logger;
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExcelVO;
import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogRespVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* API 访问日志 Convert
*
* @author 芋道源码
*/
@Mapper
public interface ApiAccessLogConvert {
ApiAccessLogConvert INSTANCE = Mappers.getMapper(ApiAccessLogConvert.class);
ApiAccessLogRespVO convert(ApiAccessLogDO bean);
List<ApiAccessLogRespVO> convertList(List<ApiAccessLogDO> list);
PageResult<ApiAccessLogRespVO> convertPage(PageResult<ApiAccessLogDO> page);
List<ApiAccessLogExcelVO> convertList02(List<ApiAccessLogDO> list);
ApiAccessLogDO convert(ApiAccessLogCreateReqDTO bean);
}

View File

@@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.infra.convert.logger;
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExcelVO;
import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogRespVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* API 错误日志 Convert
*
* @author 芋道源码
*/
@Mapper
public interface ApiErrorLogConvert {
ApiErrorLogConvert INSTANCE = Mappers.getMapper(ApiErrorLogConvert.class);
ApiErrorLogRespVO convert(ApiErrorLogDO bean);
PageResult<ApiErrorLogRespVO> convertPage(PageResult<ApiErrorLogDO> page);
List<ApiErrorLogExcelVO> convertList02(List<ApiErrorLogDO> list);
ApiErrorLogDO convert(ApiErrorLogCreateReqDTO bean);
}

View File

@@ -0,0 +1,6 @@
/**
* 提供 POJO 类的实体转换
*
* 目前使用 MapStruct 框架
*/
package cn.iocoder.yudao.module.infra.convert;

View File

@@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.infra.convert.redis;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyRespVO;
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.List;
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(Integer.valueOf(StrUtil.subBetween((String) value, "calls=", ",")))
.usec(Long.valueOf(StrUtil.subBetween((String) value, "usec=", ",")))
.build());
});
return respVO;
}
List<RedisKeyRespVO> convertList(List<RedisKeyDefine> list);
}

View File

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

View File

@@ -0,0 +1,124 @@
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.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 代码生成 column 字段定义
*
* @author 芋道源码
*/
@TableName(value = "infra_codegen_column", autoResultMap = true)
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class CodegenColumnDO extends BaseDO {
/**
* ID 编号
*/
@TableId
private Long id;
/**
* 表编号
*
* 关联 {@link CodegenTableDO#getId()}
*/
private Long tableId;
// ========== 表相关字段 ==========
/**
* 字段名
*/
private String columnName;
/**
* 字段类型
*/
private String columnType;
/**
* 字段描述
*/
private String columnComment;
/**
* 是否允许为空
*/
private Boolean nullable;
/**
* 是否主键
*/
private Boolean primaryKey;
/**
* 是否自增
*/
private Boolean autoIncrement;
/**
* 排序
*/
private Integer ordinalPosition;
// ========== Java 相关字段 ==========
/**
* Java 属性类型
*
* 例如说 String、Boolean 等等
*/
private String javaType;
/**
* Java 属性名
*/
// @NotBlank(message = "Java属性不能为空")
private String javaField;
/**
* 字典类型
*
* 关联 DictTypeDO 的 type 属性
*/
private String dictType;
/**
* 数据示例,主要用于生成 Swagger 注解的 example 字段
*/
private String example;
// ========== CRUD 相关字段 ==========
/**
* 是否为 Create 创建操作的字段
*/
private Boolean createOperation;
/**
* 是否为 Update 更新操作的字段
*/
private Boolean updateOperation;
/**
* 是否为 List 查询操作的字段
*/
private Boolean listOperation;
/**
* List 查询操作的条件类型
*
* 枚举 {@link CodegenColumnListConditionEnum}
*/
private String listOperationCondition;
/**
* 是否为 List 查询操作的返回字段
*/
private Boolean listOperationResult;
// ========== UI 相关字段 ==========
/**
* 显示类型
*
* 枚举 {@link CodegenColumnHtmlTypeEnum}
*/
private String htmlType;
}

View File

@@ -0,0 +1,102 @@
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.CodegenSceneEnum;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 代码生成 table 表定义
*
* @author 芋道源码
*/
@TableName(value = "infra_codegen_table", autoResultMap = true)
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class CodegenTableDO extends BaseDO {
/**
* ID 编号
*/
private Long id;
/**
* 导入类型
*
* 枚举 {@link CodegenTemplateTypeEnum}
*/
private Integer importType;
/**
* 生成场景
*
* 枚举 {@link CodegenSceneEnum}
*/
private Integer scene;
// ========== 表相关字段 ==========
/**
* 表名称
*/
private String tableName;
/**
* 表描述
*/
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;
// ========== 菜单相关字段 ==========
/**
* 父菜单编号
*
* 关联 MenuDO 的 id 属性
*/
private Long parentMenuId;
}

View File

@@ -0,0 +1,54 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.codegen;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data;
/**
* MySQL 数据库中的 column 字段定义
*
* @author 芋道源码
*/
@TableName(value = "information_schema.columns", autoResultMap = true)
@Data
@Builder
public class SchemaColumnDO {
/**
* 表名称
*/
private String tableName;
/**
* 字段名
*/
private String columnName;
/**
* 字段类型
*/
private String columnType;
/**
* 字段描述
*/
private String columnComment;
/**
* 是否允许为空
*/
@TableField("case when is_nullable = 'yes' then '1' else '0' end")
private Boolean nullable;
/**
* 是否主键
*/
@TableField("case when column_key = 'PRI' then '1' else '0' end")
private Boolean primaryKey;
/**
* 是否自增
*/
@TableField("case when extra = 'auto_increment' then '1' else '0' end")
private Boolean autoIncrement;
/**
* 排序字段
*/
private Integer ordinalPosition;
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.codegen;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data;
import java.util.Date;
/**
* MySQL 数据库中的 table 表定义
*
* @author 芋道源码
*/
@TableName(value = "information_schema.tables", autoResultMap = true)
@Data
@Builder
public class SchemaTableDO {
/**
* 数据库
*/
private String tableSchema;
/**
* 表名称
*/
private String tableName;
/**
* 表描述
*/
private String tableComment;
/**
* 创建时间
*/
private Date createTime;
}

View File

@@ -0,0 +1,65 @@
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.TableField;
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")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ConfigDO extends BaseDO {
/**
* 参数主键
*/
@TableId
private Long id;
/**
* 参数分组
*/
@TableField("`group`")
private String group;
/**
* 参数名称
*/
private String name;
/**
* 参数键名
*/
@TableField("`key`")
private String key;
/**
* 参数键值
*/
private String value;
/**
* 参数类型
*
* 枚举 {@link ConfigTypeEnum}
*/
@TableField("`type`")
private Integer type;
/**
* 是否敏感
*
* 对于敏感配置,需要管理权限才能查看
*/
@TableField("`sensitive`")
private Boolean sensitive;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,56 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.file;
import cn.iocoder.yudao.framework.file.core.client.FileClientConfig;
import cn.iocoder.yudao.framework.file.core.enums.FileStorageEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.*;
/**
* 文件配置表
*
* @author 芋道源码
*/
@Data
@TableName(value = "infra_file_config", autoResultMap = true)
@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 = JacksonTypeHandler.class)
private FileClientConfig config;
}

View File

@@ -0,0 +1,45 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.file;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* 文件内容表
*
* 专门用于存储 {@link cn.iocoder.yudao.framework.file.core.client.db.DBFileClient} 的文件内容
*
* @author 芋道源码
*/
@Data
@TableName("infra_file_content")
@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;
}

View File

@@ -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.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.io.InputStream;
/**
* 文件表
* 每次文件上传,都会记录一条记录到该表中
*
* @author 芋道源码
*/
@Data
@TableName("infra_file")
@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 path;
/**
* 访问地址
*/
private String url;
/**
* 文件类型
*
* 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取
*/
@TableField(value = "`type`")
private String type;
/**
* 文件大小
*/
private Integer size;
}

View File

@@ -0,0 +1,72 @@
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.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* 定时任务 DO
*
* @author 芋道源码
*/
@TableName("infra_job")
@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;
}

View File

@@ -0,0 +1,80 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.job;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.module.infra.enums.job.JobLogStatusEnum;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.util.Date;
/**
* 定时任务的执行日志
*
* @author 芋道源码
*/
@TableName("infra_job_log")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class JobLogDO extends BaseDO {
/**
* 日志编号
*/
private Long id;
/**
* 任务编号
*
* 关联 {@link JobDO#getId()}
*/
private Long jobId;
/**
* 处理器的名字
*
* 冗余字段 {@link JobDO#getHandlerName()}
*/
private String handlerName;
/**
* 处理器的参数
*
* 冗余字段 {@link JobDO#getHandlerParam()}
*/
private String handlerParam;
/**
* 第几次执行
*
* 用于区分是不是重试执行。如果是重试执行,则 index 大于 1
*/
private Integer executeIndex;
/**
* 开始执行时间
*/
private Date beginTime;
/**
* 结束执行时间
*/
private Date endTime;
/**
* 执行时长,单位:毫秒
*/
private Integer duration;
/**
* 状态
*
* 枚举 {@link JobLogStatusEnum}
*/
private Integer status;
/**
* 结果数据
*
* 成功时,使用 {@link JobHandler#execute(String)} 的结果
* 失败时,使用 {@link JobHandler#execute(String)} 的异常堆栈
*/
private String result;
}

View File

@@ -0,0 +1,107 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.logger;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.util.Date;
/**
* API 访问日志
*
* @author 芋道源码
*/
@TableName("infra_api_access_log")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ApiAccessLogDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 链路追踪编号
*
* 一般来说通过链路追踪编号可以将访问日志错误日志链路追踪日志logger 打印日志等,结合在一起,从而进行排错。
*/
private String traceId;
/**
* 用户编号
*/
private Long userId;
/**
* 用户类型
*
* 枚举 {@link UserTypeEnum}
*/
private Integer userType;
/**
* 应用名
*
* 目前读取 `spring.application.name` 配置项
*/
private String applicationName;
// ========== 请求相关字段 ==========
/**
* 请求方法名
*/
private String requestMethod;
/**
* 访问地址
*/
private String requestUrl;
/**
* 请求参数
*
* query: Query String
* body: Quest Body
*/
private String requestParams;
/**
* 用户 IP
*/
private String userIp;
/**
* 浏览器 UA
*/
private String userAgent;
// ========== 执行相关字段 ==========
/**
* 开始请求时间
*/
private Date beginTime;
/**
* 结束请求时间
*/
private Date endTime;
/**
* 执行时长,单位:毫秒
*/
private Integer duration;
/**
* 结果码
*
* 目前使用的 {@link CommonResult#getCode()} 属性
*/
private Integer resultCode;
/**
* 结果提示
*
* 目前使用的 {@link CommonResult#getMsg()} 属性
*/
private String resultMsg;
}

View File

@@ -0,0 +1,154 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.logger;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.infra.enums.logger.ApiErrorLogProcessStatusEnum;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.util.Date;
/**
* API 异常数据
*
* @author 芋道源码
*/
@TableName("infra_api_error_log")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ApiErrorLogDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 用户编号
*/
private Long userId;
/**
* 链路追踪编号
*
* 一般来说通过链路追踪编号可以将访问日志错误日志链路追踪日志logger 打印日志等,结合在一起,从而进行排错。
*/
private String traceId;
/**
* 用户类型
*
* 枚举 {@link UserTypeEnum}
*/
private Integer userType;
/**
* 应用名
*
* 目前读取 spring.application.name
*/
private String applicationName;
// ========== 请求相关字段 ==========
/**
* 请求方法名
*/
private String requestMethod;
/**
* 访问地址
*/
private String requestUrl;
/**
* 请求参数
*
* query: Query String
* body: Quest Body
*/
private String requestParams;
/**
* 用户 IP
*/
private String userIp;
/**
* 浏览器 UA
*/
private String userAgent;
// ========== 异常相关字段 ==========
/**
* 异常发生时间
*/
private Date exceptionTime;
/**
* 异常名
*
* {@link Throwable#getClass()} 的类全名
*/
private String exceptionName;
/**
* 异常导致的消息
*
* {@link cn.hutool.core.exceptions.ExceptionUtil#getMessage(Throwable)}
*/
private String exceptionMessage;
/**
* 异常导致的根消息
*
* {@link cn.hutool.core.exceptions.ExceptionUtil#getRootCauseMessage(Throwable)}
*/
private String exceptionRootCauseMessage;
/**
* 异常的栈轨迹
*
* {@link org.apache.commons.lang3.exception.ExceptionUtils#getStackTrace(Throwable)}
*/
private String exceptionStackTrace;
/**
* 异常发生的类全名
*
* {@link StackTraceElement#getClassName()}
*/
private String exceptionClassName;
/**
* 异常发生的类文件
*
* {@link StackTraceElement#getFileName()}
*/
private String exceptionFileName;
/**
* 异常发生的方法名
*
* {@link StackTraceElement#getMethodName()}
*/
private String exceptionMethodName;
/**
* 异常发生的方法所在行
*
* {@link StackTraceElement#getLineNumber()}
*/
private Integer exceptionLineNumber;
// ========== 处理相关字段 ==========
/**
* 处理状态
*
* 枚举 {@link ApiErrorLogProcessStatusEnum}
*/
private Integer processStatus;
/**
* 处理时间
*/
private Date processTime;
/**
* 处理用户编号
*
* 关联 cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO.SysUserDO#getId()
*/
private Long processUserId;
}

View File

@@ -0,0 +1,48 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.test;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* 字典类型 DO
*
* @author 芋道源码
*/
@TableName("infra_test_demo")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TestDemoDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 名字
*/
private String name;
/**
* 状态
*/
private Integer status;
/**
* 类型
*/
private Integer type;
/**
* 分类
*/
private Integer category;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface CodegenColumnMapper extends BaseMapperX<CodegenColumnDO> {
default List<CodegenColumnDO> selectListByTableId(Long tableId) {
return selectList(new QueryWrapper<CodegenColumnDO>().eq("table_id", tableId)
.orderByAsc("ordinal_position"));
}
default void deleteListByTableId(Long tableId) {
delete(new QueryWrapper<CodegenColumnDO>().eq("table_id", tableId));
}
}

View File

@@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CodegenTableMapper extends BaseMapperX<CodegenTableDO> {
default CodegenTableDO selectByTableName(String tableName) {
return selectOne(new QueryWrapper<CodegenTableDO>().eq("table_name", tableName));
}
default PageResult<CodegenTableDO> selectPage(CodegenTablePageReqVO pageReqVO) {
return selectPage(pageReqVO, new QueryWrapperX<CodegenTableDO>()
.likeIfPresent("table_name", pageReqVO.getTableName())
.likeIfPresent("table_comment", pageReqVO.getTableComment())
.betweenIfPresent("create_time", pageReqVO.getBeginCreateTime(), pageReqVO.getEndCreateTime()));
}
}

View File

@@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface SchemaColumnMapper extends BaseMapperX<SchemaColumnDO> {
default List<SchemaColumnDO> selectListByTableName(String tableSchema, String tableName) {
return selectList(new QueryWrapper<SchemaColumnDO>().eq("table_name", tableName)
.eq("table_schema", tableSchema)
.orderByAsc("ordinal_position"));
}
}

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