Prechádzať zdrojové kódy

初始化 API 错误日志的后端 API

YunaiV 4 rokov pred
rodič
commit
1b3e665be6
15 zmenil súbory, kde vykonal 543 pridanie a 8 odobranie
  1. 74 0
      src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiErrorLogController.java
  2. 96 0
      src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogBaseVO.java
  3. 92 0
      src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExcelVO.java
  4. 39 0
      src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java
  5. 44 0
      src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java
  6. 29 0
      src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogRespVO.java
  7. 31 0
      src/main/java/cn/iocoder/dashboard/modules/infra/convert/logger/InfApiErrorLogConvert.java
  8. 4 3
      src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java
  9. 45 0
      src/main/java/cn/iocoder/dashboard/modules/infra/dal/mysql/logger/InfApiErrorLogMapper.java
  10. 4 0
      src/main/java/cn/iocoder/dashboard/modules/infra/enums/InfErrorCodeConstants.java
  11. 31 0
      src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogService.java
  12. 43 0
      src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java
  13. 4 2
      src/main/java/cn/iocoder/dashboard/modules/system/enums/dict/SysDictTypeEnum.java
  14. 4 1
      src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java
  15. 3 2
      src/main/resources/codegen/java/dal/mapper.vm

+ 74 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiErrorLogController.java

@@ -0,0 +1,74 @@
+package cn.iocoder.dashboard.modules.infra.controller.logger;
+
+import cn.iocoder.dashboard.common.pojo.CommonResult;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
+import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExcelVO;
+import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO;
+import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO;
+import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogRespVO;
+import cn.iocoder.dashboard.modules.infra.convert.logger.InfApiErrorLogConvert;
+import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiErrorLogDO;
+import cn.iocoder.dashboard.modules.infra.service.logger.InfApiErrorLogService;
+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.dashboard.common.pojo.CommonResult.success;
+import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+
+@Api(tags = "API 错误日志")
+@RestController
+@RequestMapping("/infra/api-error-log")
+@Validated
+public class InfApiErrorLogController {
+
+    @Resource
+    private InfApiErrorLogService 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<InfApiErrorLogRespVO>> getApiErrorLogPage(@Valid InfApiErrorLogPageReqVO pageVO) {
+        PageResult<InfApiErrorLogDO> pageResult = apiErrorLogService.getApiErrorLogPage(pageVO);
+        return success(InfApiErrorLogConvert.INSTANCE.convertPage(pageResult));
+    }
+
+    @GetMapping("/export-excel")
+    @ApiOperation("导出 API 错误日志 Excel")
+    @PreAuthorize("@ss.hasPermission('infra:api-error-log:export')")
+    @OperateLog(type = EXPORT)
+    public void exportApiErrorLogExcel(@Valid InfApiErrorLogExportReqVO exportReqVO,
+              HttpServletResponse response) throws IOException {
+        List<InfApiErrorLogDO> list = apiErrorLogService.getApiErrorLogList(exportReqVO);
+        // 导出 Excel
+        List<InfApiErrorLogExcelVO> datas = InfApiErrorLogConvert.INSTANCE.convertList02(list);
+        ExcelUtils.write(response, "API 错误日志.xls", "数据", InfApiErrorLogExcelVO.class, datas);
+    }
+
+}

+ 96 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogBaseVO.java

@@ -0,0 +1,96 @@
+package cn.iocoder.dashboard.modules.infra.controller.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.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+* API 错误日志 Base VO,提供给添加、修改、详细的子 VO 使用
+* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+*/
+@Data
+public class InfApiErrorLogBaseVO {
+
+    @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;
+
+}

+ 92 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExcelVO.java

@@ -0,0 +1,92 @@
+package cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog;
+
+import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert;
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+import static cn.iocoder.dashboard.modules.system.enums.dict.SysDictTypeEnum.INF_API_ERROR_LOG_PROCESS_STATUS;
+import static cn.iocoder.dashboard.modules.system.enums.dict.SysDictTypeEnum.USER_TYPE;
+
+/**
+ * API 错误日志 Excel VO
+ *
+ * @author 芋道源码
+ */
+@Data
+public class InfApiErrorLogExcelVO {
+
+    @ExcelProperty("编号")
+    private Integer id;
+
+    @ExcelProperty("链路追踪编号")
+    private String traceId;
+
+    @ExcelProperty("用户编号")
+    private Integer userId;
+
+    @ExcelProperty(value = "用户类型", converter = DictConvert.class)
+    @DictFormat(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(INF_API_ERROR_LOG_PROCESS_STATUS)
+    private Integer processStatus;
+
+    @ExcelProperty("处理时间")
+    private Date processTime;
+
+    @ExcelProperty("处理用户编号")
+    private Integer processUserId;
+
+}

+ 39 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java

@@ -0,0 +1,39 @@
+package cn.iocoder.dashboard.modules.infra.controller.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.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel(value = "API 错误日志 Excel 导出 Request VO", description = "参数和 InfApiErrorLogPageReqVO 是一致的")
+@Data
+public class InfApiErrorLogExportReqVO {
+
+    @ApiModelProperty(value = "用户编号", example = "666")
+    private Integer 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;
+
+}

+ 44 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java

@@ -0,0 +1,44 @@
+package cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog;
+
+import cn.iocoder.dashboard.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.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel("API 错误日志分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class InfApiErrorLogPageReqVO extends PageParam {
+
+    @ApiModelProperty(value = "用户编号", example = "666")
+    private Integer 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;
+
+}

+ 29 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogRespVO.java

@@ -0,0 +1,29 @@
+package cn.iocoder.dashboard.modules.infra.controller.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 InfApiErrorLogRespVO extends InfApiErrorLogBaseVO {
+
+    @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;
+
+}

+ 31 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/convert/logger/InfApiErrorLogConvert.java

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

+ 4 - 3
src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java

@@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.infra.dal.dataobject.logger;
 import cn.iocoder.dashboard.common.enums.UserTypeEnum;
 import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.dashboard.modules.infra.enums.logger.ApiErrorLogProcessStatusEnum;
+import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.*;
 
@@ -25,7 +26,7 @@ public class InfApiErrorLogDO extends BaseDO {
     /**
      * 编号
      */
-    private Integer id;
+    private Long id;
     /**
      * 用户编号
      */
@@ -143,9 +144,9 @@ public class InfApiErrorLogDO extends BaseDO {
      */
     private Date processTime;
     /**
-     * 处理管理员编号
+     * 处理用户编号
      *
-     * 关联 {@link}
+     * 关联 {@link SysUserDO#getId()}
      */
     private Integer processUserId;
 

+ 45 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/dal/mysql/logger/InfApiErrorLogMapper.java

@@ -0,0 +1,45 @@
+package cn.iocoder.dashboard.modules.infra.dal.mysql.logger;
+
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
+import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO;
+import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO;
+import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiErrorLogDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * API 错误日志 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface InfApiErrorLogMapper extends BaseMapperX<InfApiErrorLogDO> {
+
+    default PageResult<InfApiErrorLogDO> selectPage(InfApiErrorLogPageReqVO reqVO) {
+        return selectPage(reqVO, new QueryWrapperX<InfApiErrorLogDO>()
+                .eqIfPresent("user_id", reqVO.getUserId())
+                .eqIfPresent("user_type", reqVO.getUserType())
+                .eqIfPresent("application_name", reqVO.getApplicationName())
+                .likeIfPresent("request_url", reqVO.getRequestUrl())
+                .betweenIfPresent("exception_time", reqVO.getBeginExceptionTime(), reqVO.getEndExceptionTime())
+                .eqIfPresent("process_status", reqVO.getProcessStatus())
+                .orderByDesc("id")
+        );
+    }
+
+    default List<InfApiErrorLogDO> selectList(InfApiErrorLogExportReqVO reqVO) {
+        return selectList(new QueryWrapperX<InfApiErrorLogDO>()
+                .eqIfPresent("user_id", reqVO.getUserId())
+                .eqIfPresent("user_type", reqVO.getUserType())
+                .eqIfPresent("application_name", reqVO.getApplicationName())
+                .likeIfPresent("request_url", reqVO.getRequestUrl())
+                .betweenIfPresent("exception_time", reqVO.getBeginExceptionTime(), reqVO.getEndExceptionTime())
+                .eqIfPresent("process_status", reqVO.getProcessStatus())
+				.orderByDesc("id")
+        );
+    }
+
+}

+ 4 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/enums/InfErrorCodeConstants.java

@@ -23,4 +23,8 @@ public interface InfErrorCodeConstants {
     ErrorCode JOB_UPDATE_ONLY_NORMAL_STATUS = new ErrorCode(1001001004, "只有开启状态的任务,才可以修改");
     ErrorCode JOB_CRON_EXPRESSION_VALID = new ErrorCode(1001001005, "CRON 表达式不正确");
 
+    // ========== API 错误日志 1001002000 ==========
+    ErrorCode API_ERROR_LOG_NOT_FOUND = new ErrorCode(1001002000, "API 错误日志不存在");
+    ErrorCode API_ERROR_LOG_PROCESSED = new ErrorCode(1001002001, "API 错误日志已处理");
+
 }

+ 31 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogService.java

@@ -1,6 +1,12 @@
 package cn.iocoder.dashboard.modules.infra.service.logger;
 
+import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.framework.logger.apilog.core.service.ApiErrorLogFrameworkService;
+import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO;
+import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO;
+import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiErrorLogDO;
+
+import java.util.List;
 
 /**
  * API 错误日志 Service 接口
@@ -9,4 +15,29 @@ import cn.iocoder.dashboard.framework.logger.apilog.core.service.ApiErrorLogFram
  */
 public interface InfApiErrorLogService extends ApiErrorLogFrameworkService {
 
+    /**
+     * 获得 API 错误日志分页
+     *
+     * @param pageReqVO 分页查询
+     * @return API 错误日志分页
+     */
+    PageResult<InfApiErrorLogDO> getApiErrorLogPage(InfApiErrorLogPageReqVO pageReqVO);
+
+    /**
+     * 获得 API 错误日志列表, 用于 Excel 导出
+     *
+     * @param exportReqVO 查询条件
+     * @return API 错误日志分页
+     */
+    List<InfApiErrorLogDO> getApiErrorLogList(InfApiErrorLogExportReqVO exportReqVO);
+
+    /**
+     * 更新 API 错误日志已处理
+     *
+     * @param id API 日志编号
+     * @param processStatus 处理结果
+     * @param processUserId 处理人
+     */
+    void updateApiErrorLogProcess(Long id, Integer processStatus, Long processUserId);
+
 }

+ 43 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java

@@ -1,11 +1,25 @@
 package cn.iocoder.dashboard.modules.infra.service.logger.impl;
 
+import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiErrorLogCreateDTO;
+import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO;
+import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO;
+import cn.iocoder.dashboard.modules.infra.convert.logger.InfApiErrorLogConvert;
+import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiErrorLogDO;
+import cn.iocoder.dashboard.modules.infra.dal.mysql.logger.InfApiErrorLogMapper;
+import cn.iocoder.dashboard.modules.infra.enums.logger.ApiErrorLogProcessStatusEnum;
 import cn.iocoder.dashboard.modules.infra.service.logger.InfApiErrorLogService;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
+import javax.annotation.Resource;
+import java.util.List;
+
+import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_NOT_FOUND;
+import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_PROCESSED;
+
 /**
  * API 错误日志 Service 实现类
  *
@@ -15,10 +29,39 @@ import org.springframework.validation.annotation.Validated;
 @Validated
 public class InfApiErrorLogServiceImpl implements InfApiErrorLogService {
 
+    @Resource
+    private InfApiErrorLogMapper apiErrorLogMapper;
+
     @Override
     @Async
     public void createApiErrorLogAsync(ApiErrorLogCreateDTO createDTO) {
+        InfApiErrorLogDO apiErrorLog = InfApiErrorLogConvert.INSTANCE.convert(createDTO);
+        apiErrorLog.setProcessStatus(ApiErrorLogProcessStatusEnum.INIT.getStatus());
+        apiErrorLogMapper.insert(apiErrorLog);
+    }
 
+    @Override
+    public PageResult<InfApiErrorLogDO> getApiErrorLogPage(InfApiErrorLogPageReqVO pageReqVO) {
+        return apiErrorLogMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public List<InfApiErrorLogDO> getApiErrorLogList(InfApiErrorLogExportReqVO exportReqVO) {
+        return apiErrorLogMapper.selectList(exportReqVO);
+    }
+
+    @Override
+    public void updateApiErrorLogProcess(Long id, Integer processStatus, Long processUserId) {
+        InfApiErrorLogDO errorLog = apiErrorLogMapper.selectById(id);
+        if (errorLog == null) {
+            throw exception(API_ERROR_LOG_NOT_FOUND);
+        }
+        if (!ApiErrorLogProcessStatusEnum.INIT.getStatus().equals(errorLog.getProcessStatus())) {
+            throw exception(API_ERROR_LOG_PROCESSED);
+        }
+        // 标记处理
+        apiErrorLogMapper.updateById(InfApiErrorLogDO.builder().id(id).processStatus(processStatus)
+                .processUserId(processStatus).build());
     }
 
 }

+ 4 - 2
src/main/java/cn/iocoder/dashboard/modules/system/enums/dict/SysDictTypeEnum.java

@@ -21,8 +21,10 @@ public enum SysDictTypeEnum {
 
     INF_REDIS_TIMEOUT_TYPE("inf_redis_timeout_type"),  // Redis 超时类型
     INF_JOB_STATUS("inf_job_status"), // 定时任务状态的枚举
-    INF_JOB_LOG_STATUS("inf_job_log_status") // 定时任务日志状态的枚举
-    ,;
+    INF_JOB_LOG_STATUS("inf_job_log_status"), // 定时任务日志状态的枚举
+    INF_API_ERROR_LOG_PROCESS_STATUS("inf_api_error_log_process_status"), // API 错误日志的处理状态的枚举
+
+    ;
 
 
     /**

+ 4 - 1
src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java

@@ -252,7 +252,10 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
 
     @Override
     public List<ToolSchemaTableDO> getSchemaTableList(String tableName, String tableComment) {
-        return schemaTableMapper.selectList(codegenProperties.getDbSchemas(), tableName, tableComment);
+        List<ToolSchemaTableDO> tables = schemaTableMapper.selectList(codegenProperties.getDbSchemas(), tableName, tableComment);
+        // TODO 强制移除 Quartz 的表,未来做成可配置
+        tables.removeIf(table -> table.getTableName().startsWith("QRTZ_"));
+        return tables;
     }
 
 //    /**

+ 3 - 2
src/main/resources/codegen/java/dal/mapper.vm

@@ -52,13 +52,14 @@ public interface ${table.className}Mapper extends BaseMapperX<${table.className}
     default PageResult<${table.className}DO> selectPage(${table.className}PageReqVO reqVO) {
         return selectPage(reqVO, new QueryWrapperX<${table.className}DO>()
 			#listCondition()
-			.orderByDesc("id")# 大多数情况下,id 倒序
+                .orderByDesc("id")## 大多数情况下,id 倒序
         );
     }
 
     default List<${table.className}DO> selectList(${table.className}ExportReqVO reqVO) {
         return selectList(new QueryWrapperX<${table.className}DO>()
-			#listCondition()# 大多数情况下,id 倒序
+			#listCondition()
+                .orderByDesc("id")## 大多数情况下,id 倒序
         );
     }