mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-07-13 18:45:06 +08:00
【重构】V2 操作日志转正,基于注解的可使用变量、可以自定义函数的通用操作日志组件
This commit is contained in:
@ -1,13 +1,11 @@
|
||||
package cn.iocoder.yudao.module.system.api.logger;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogPageReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogRespDTO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
|
||||
import cn.iocoder.yudao.module.system.service.logger.OperateLogService;
|
||||
import com.fhs.core.trans.anno.TransMethodResult;
|
||||
import jakarta.annotation.Resource;
|
||||
@ -28,24 +26,16 @@ public class OperateLogApiImpl implements OperateLogApi {
|
||||
private OperateLogService operateLogService;
|
||||
|
||||
@Override
|
||||
@Async
|
||||
public void createOperateLog(OperateLogCreateReqDTO createReqDTO) {
|
||||
operateLogService.createOperateLog(createReqDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Async
|
||||
public void createOperateLogV2(OperateLogV2CreateReqDTO createReqDTO) {
|
||||
operateLogService.createOperateLogV2(createReqDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@TransMethodResult
|
||||
public PageResult<OperateLogV2RespDTO> getOperateLogPage(OperateLogV2PageReqDTO pageReqVO) {
|
||||
PageResult<OperateLogV2DO> operateLogPage = operateLogService.getOperateLogPage(pageReqVO);
|
||||
if (CollUtil.isEmpty(operateLogPage.getList())) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
return BeanUtils.toBean(operateLogPage, OperateLogV2RespDTO.class);
|
||||
public PageResult<OperateLogRespDTO> getOperateLogPage(OperateLogPageReqDTO pageReqVO) {
|
||||
PageResult<OperateLogDO> operateLogPage = operateLogService.getOperateLogPage(pageReqVO);
|
||||
return BeanUtils.toBean(operateLogPage, OperateLogRespDTO.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,20 +13,23 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
|
||||
@Data
|
||||
public class OperateLogPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "用户编号", example = "芋道")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "操作模块业务编号", example = "1")
|
||||
private Long bizId;
|
||||
|
||||
@Schema(description = "操作模块,模拟匹配", example = "订单")
|
||||
private String module;
|
||||
private String type;
|
||||
|
||||
@Schema(description = "用户昵称,模拟匹配", example = "芋道")
|
||||
private String userNickname;
|
||||
@Schema(description = "操作名,模拟匹配", example = "创建订单")
|
||||
private String subType;
|
||||
|
||||
@Schema(description = "操作分类,参见 OperateLogTypeEnum 枚举类", example = "1")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "操作状态", example = "true")
|
||||
private Boolean success;
|
||||
@Schema(description = "操作明细,模拟匹配", example = "修改编号为 1 的用户信息")
|
||||
private String action;
|
||||
|
||||
@Schema(description = "开始时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] startTime;
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.fhs.core.trans.anno.Trans;
|
||||
@ -14,7 +11,6 @@ import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
@Schema(description = "管理后台 - 操作日志 Response VO")
|
||||
@Data
|
||||
@ -29,31 +25,29 @@ public class OperateLogRespVO implements VO {
|
||||
private String traceId;
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@Trans(type = TransType.SIMPLE, target = AdminUserDO.class, fields = "nickname", ref = "userNickname")
|
||||
@Trans(type = TransType.SIMPLE, target = AdminUserDO.class, fields = "nickname", ref = "userName")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
|
||||
@ExcelProperty("操作人")
|
||||
private String userNickname;
|
||||
private String userName;
|
||||
|
||||
@Schema(description = "操作模块", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单")
|
||||
@ExcelProperty("操作模块")
|
||||
private String module;
|
||||
@Schema(description = "操作模块类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单")
|
||||
@ExcelProperty("操作模块类型")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "操作名", requiredMode = Schema.RequiredMode.REQUIRED, example = "创建订单")
|
||||
@ExcelProperty("操作名")
|
||||
private String name;
|
||||
private String subType;
|
||||
|
||||
@Schema(description = "操作分类,参见 OperateLogTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty(value = "操作类型", converter = DictConvert.class)
|
||||
@DictFormat(DictTypeConstants.OPERATE_TYPE)
|
||||
private Integer type;
|
||||
@Schema(description = "操作模块业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty("操作模块业务编号")
|
||||
private Long bizId;
|
||||
|
||||
@Schema(description = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。")
|
||||
private String content;
|
||||
private String action;
|
||||
|
||||
@Schema(description = "拓展字段", example = "{'orderId': 1}")
|
||||
private Map<String, Object> exts;
|
||||
private String extra;
|
||||
|
||||
@Schema(description = "请求方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "GET")
|
||||
@NotEmpty(message = "请求方法名不能为空")
|
||||
@ -68,28 +62,7 @@ public class OperateLogRespVO implements VO {
|
||||
@Schema(description = "浏览器 UserAgent", requiredMode = Schema.RequiredMode.REQUIRED, example = "Mozilla/5.0")
|
||||
private String userAgent;
|
||||
|
||||
@Schema(description = "Java 方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "cn.iocoder.yudao.adminserver.UserController.save(...)")
|
||||
private String javaMethod;
|
||||
|
||||
@Schema(description = "Java 方法的参数")
|
||||
private String javaMethodArgs;
|
||||
|
||||
@Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("操作日志")
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@Schema(description = "执行时长,单位:毫秒", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("执行时长")
|
||||
private Integer duration;
|
||||
|
||||
@Schema(description = "结果码", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty(value = "结果码")
|
||||
private Integer resultCode;
|
||||
|
||||
@Schema(description = "结果提示")
|
||||
private String resultMsg;
|
||||
|
||||
@Schema(description = "结果数据")
|
||||
private String resultData;
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
@ -1,19 +1,11 @@
|
||||
package cn.iocoder.yudao.module.system.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 cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 操作日志表
|
||||
@ -23,19 +15,8 @@ import java.util.Map;
|
||||
@TableName(value = "system_operate_log", autoResultMap = true)
|
||||
@KeySequence("system_operate_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class OperateLogDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* {@link #javaMethodArgs} 的最大长度
|
||||
*/
|
||||
public static final Integer JAVA_METHOD_ARGS_MAX_LENGTH = 8000;
|
||||
|
||||
/**
|
||||
* {@link #resultData} 的最大长度
|
||||
*/
|
||||
public static final Integer RESULT_MAX_LENGTH = 4000;
|
||||
|
||||
/**
|
||||
* 日志主键
|
||||
*/
|
||||
@ -60,30 +41,29 @@ public class OperateLogDO extends BaseDO {
|
||||
*/
|
||||
private Integer userType;
|
||||
/**
|
||||
* 操作模块
|
||||
* 操作模块类型
|
||||
*/
|
||||
private String module;
|
||||
private String type;
|
||||
/**
|
||||
* 操作名
|
||||
*/
|
||||
private String name;
|
||||
private String subType;
|
||||
/**
|
||||
* 操作分类
|
||||
*
|
||||
* 枚举 {@link OperateTypeEnum}
|
||||
* 操作模块业务编号
|
||||
*/
|
||||
private Integer type;
|
||||
private Long bizId;
|
||||
/**
|
||||
* 操作内容,记录整个操作的明细
|
||||
* 日志内容,记录整个操作的明细
|
||||
*
|
||||
* 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。
|
||||
*/
|
||||
private String content;
|
||||
private String action;
|
||||
/**
|
||||
* 拓展字段,有些复杂的业务,需要记录一些字段
|
||||
* 例如说,记录订单编号,则可以添加 key 为 "orderId",value 为订单编号
|
||||
* 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 )
|
||||
*
|
||||
* 例如说,记录订单编号,{ orderId: "1"}
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private Map<String, Object> exts;
|
||||
private String extra;
|
||||
|
||||
/**
|
||||
* 请求方法名
|
||||
@ -102,43 +82,4 @@ public class OperateLogDO extends BaseDO {
|
||||
*/
|
||||
private String userAgent;
|
||||
|
||||
/**
|
||||
* Java 方法名
|
||||
*/
|
||||
private String javaMethod;
|
||||
/**
|
||||
* Java 方法的参数
|
||||
*
|
||||
* 实际格式为 Map<String, Object>
|
||||
* 不使用 @TableField(typeHandler = FastjsonTypeHandler.class) 注解的原因是,数据库存储有长度限制,会进行裁剪,会导致 JSON 反序列化失败
|
||||
* 其中,key 为参数名,value 为参数值
|
||||
*/
|
||||
private String javaMethodArgs;
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
private LocalDateTime startTime;
|
||||
/**
|
||||
* 执行时长,单位:毫秒
|
||||
*/
|
||||
private Integer duration;
|
||||
/**
|
||||
* 结果码
|
||||
*
|
||||
* 目前使用的 {@link CommonResult#getCode()} 属性
|
||||
*/
|
||||
private Integer resultCode;
|
||||
/**
|
||||
* 结果提示
|
||||
*
|
||||
* 目前使用的 {@link CommonResult#getMsg()} 属性
|
||||
*/
|
||||
private String resultMsg;
|
||||
/**
|
||||
* 结果数据
|
||||
*
|
||||
* 如果是对象,则使用 JSON 格式化
|
||||
*/
|
||||
private String resultData;
|
||||
|
||||
}
|
||||
|
@ -1,87 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.dal.dataobject.logger;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 操作日志表 V2
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "system_operate_log_v2", autoResultMap = true)
|
||||
@KeySequence("system_operate_log_seq_v2") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class OperateLogV2DO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 日志主键
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 链路追踪编号
|
||||
*
|
||||
* 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。
|
||||
*/
|
||||
private String traceId;
|
||||
/**
|
||||
* 用户编号
|
||||
*
|
||||
* 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户类型
|
||||
*
|
||||
* 关联 {@link UserTypeEnum}
|
||||
*/
|
||||
private Integer userType;
|
||||
/**
|
||||
* 操作模块类型
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 操作名
|
||||
*/
|
||||
private String subType;
|
||||
/**
|
||||
* 操作模块业务编号
|
||||
*/
|
||||
private Long bizId;
|
||||
/**
|
||||
* 日志内容,记录整个操作的明细
|
||||
*
|
||||
* 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。
|
||||
*/
|
||||
private String action;
|
||||
/**
|
||||
* 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 )
|
||||
*
|
||||
* 例如说,记录订单编号,{ orderId: "1"}
|
||||
*/
|
||||
private String extra;
|
||||
|
||||
/**
|
||||
* 请求方法名
|
||||
*/
|
||||
private String requestMethod;
|
||||
/**
|
||||
* 请求地址
|
||||
*/
|
||||
private String requestUrl;
|
||||
/**
|
||||
* 用户 IP
|
||||
*/
|
||||
private String userIp;
|
||||
/**
|
||||
* 浏览器 UA
|
||||
*/
|
||||
private String userAgent;
|
||||
|
||||
}
|
@ -1,31 +1,33 @@
|
||||
package cn.iocoder.yudao.module.system.dal.mysql.logger;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
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.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogPageReqDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Mapper
|
||||
public interface OperateLogMapper extends BaseMapperX<OperateLogDO> {
|
||||
|
||||
default PageResult<OperateLogDO> selectPage(OperateLogPageReqVO reqVO, Collection<Long> userIds) {
|
||||
LambdaQueryWrapperX<OperateLogDO> query = new LambdaQueryWrapperX<OperateLogDO>()
|
||||
.likeIfPresent(OperateLogDO::getModule, reqVO.getModule())
|
||||
.inIfPresent(OperateLogDO::getUserId, userIds)
|
||||
.eqIfPresent(OperateLogDO::getType, reqVO.getType())
|
||||
.betweenIfPresent(OperateLogDO::getStartTime, reqVO.getStartTime());
|
||||
if (Boolean.TRUE.equals(reqVO.getSuccess())) {
|
||||
query.eq(OperateLogDO::getResultCode, GlobalErrorCodeConstants.SUCCESS.getCode());
|
||||
} else if (Boolean.FALSE.equals(reqVO.getSuccess())) {
|
||||
query.gt(OperateLogDO::getResultCode, GlobalErrorCodeConstants.SUCCESS.getCode());
|
||||
}
|
||||
query.orderByDesc(OperateLogDO::getId); // 降序
|
||||
return selectPage(reqVO, query);
|
||||
default PageResult<OperateLogDO> selectPage(OperateLogPageReqVO pageReqDTO) {
|
||||
return selectPage(pageReqDTO, new LambdaQueryWrapperX<OperateLogDO>()
|
||||
.eqIfPresent(OperateLogDO::getUserId, pageReqDTO.getUserId())
|
||||
.eqIfPresent(OperateLogDO::getBizId, pageReqDTO.getBizId())
|
||||
.likeIfPresent(OperateLogDO::getType, pageReqDTO.getType())
|
||||
.likeIfPresent(OperateLogDO::getSubType, pageReqDTO.getSubType())
|
||||
.likeIfPresent(OperateLogDO::getAction, pageReqDTO.getAction())
|
||||
.betweenIfPresent(OperateLogDO::getCreateTime, pageReqDTO.getCreateTime())
|
||||
.orderByDesc(OperateLogDO::getId));
|
||||
}
|
||||
|
||||
default PageResult<OperateLogDO> selectPage(OperateLogPageReqDTO pageReqDTO) {
|
||||
return selectPage(pageReqDTO, new LambdaQueryWrapperX<OperateLogDO>()
|
||||
.eqIfPresent(OperateLogDO::getType, pageReqDTO.getType())
|
||||
.eqIfPresent(OperateLogDO::getBizId, pageReqDTO.getBizId())
|
||||
.eqIfPresent(OperateLogDO::getUserId, pageReqDTO.getUserId())
|
||||
.orderByDesc(OperateLogDO::getId));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.dal.mysql.logger;
|
||||
|
||||
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.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface OperateLogV2Mapper extends BaseMapperX<OperateLogV2DO> {
|
||||
|
||||
default PageResult<OperateLogV2DO> selectPage(OperateLogV2PageReqDTO pageReqDTO) {
|
||||
return selectPage(pageReqDTO, new LambdaQueryWrapperX<OperateLogV2DO>()
|
||||
.eqIfPresent(OperateLogV2DO::getType, pageReqDTO.getBizType())
|
||||
.eqIfPresent(OperateLogV2DO::getBizId, pageReqDTO.getBizId())
|
||||
.eqIfPresent(OperateLogV2DO::getUserId, pageReqDTO.getUserId())
|
||||
.orderByDesc(OperateLogV2DO::getId));
|
||||
}
|
||||
|
||||
}
|
@ -2,11 +2,9 @@ package cn.iocoder.yudao.module.system.service.logger;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogPageReqDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO;
|
||||
|
||||
/**
|
||||
* 操作日志 Service 接口
|
||||
@ -18,7 +16,7 @@ public interface OperateLogService {
|
||||
/**
|
||||
* 记录操作日志
|
||||
*
|
||||
* @param createReqDTO 操作日志请求
|
||||
* @param createReqDTO 创建请求
|
||||
*/
|
||||
void createOperateLog(OperateLogCreateReqDTO createReqDTO);
|
||||
|
||||
@ -30,21 +28,12 @@ public interface OperateLogService {
|
||||
*/
|
||||
PageResult<OperateLogDO> getOperateLogPage(OperateLogPageReqVO pageReqVO);
|
||||
|
||||
// ======================= LOG V2 =======================
|
||||
|
||||
/**
|
||||
* 记录操作日志 V2
|
||||
*
|
||||
* @param createReqDTO 创建请求
|
||||
*/
|
||||
void createOperateLogV2(OperateLogV2CreateReqDTO createReqDTO);
|
||||
|
||||
/**
|
||||
* 获得操作日志分页列表
|
||||
*
|
||||
* @param pageReqVO 分页条件
|
||||
* @return 操作日志分页列表
|
||||
*/
|
||||
PageResult<OperateLogV2DO> getOperateLogPage(OperateLogV2PageReqDTO pageReqVO);
|
||||
PageResult<OperateLogDO> getOperateLogPage(OperateLogPageReqDTO pageReqVO);
|
||||
|
||||
}
|
||||
|
@ -1,31 +1,17 @@
|
||||
package cn.iocoder.yudao.module.system.service.logger;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogPageReqDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogV2Mapper;
|
||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH;
|
||||
import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.RESULT_MAX_LENGTH;
|
||||
|
||||
/**
|
||||
* 操作日志 Service 实现类
|
||||
*
|
||||
@ -38,45 +24,21 @@ public class OperateLogServiceImpl implements OperateLogService {
|
||||
|
||||
@Resource
|
||||
private OperateLogMapper operateLogMapper;
|
||||
@Resource
|
||||
private OperateLogV2Mapper operateLogV2Mapper;
|
||||
|
||||
@Resource
|
||||
private AdminUserService userService;
|
||||
|
||||
@Override
|
||||
public void createOperateLog(OperateLogCreateReqDTO createReqDTO) {
|
||||
OperateLogDO log = BeanUtils.toBean(createReqDTO, OperateLogDO.class);
|
||||
log.setJavaMethodArgs(StrUtils.maxLength(log.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH));
|
||||
log.setResultData(StrUtils.maxLength(log.getResultData(), RESULT_MAX_LENGTH));
|
||||
operateLogMapper.insert(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<OperateLogDO> getOperateLogPage(OperateLogPageReqVO pageReqVO) {
|
||||
// 处理基于用户昵称的查询
|
||||
Collection<Long> userIds = null;
|
||||
if (StrUtil.isNotEmpty(pageReqVO.getUserNickname())) {
|
||||
userIds = convertSet(userService.getUserListByNickname(pageReqVO.getUserNickname()), AdminUserDO::getId);
|
||||
if (CollUtil.isEmpty(userIds)) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
}
|
||||
// 查询分页
|
||||
return operateLogMapper.selectPage(pageReqVO, userIds);
|
||||
}
|
||||
|
||||
// ======================= LOG V2 =======================
|
||||
|
||||
@Override
|
||||
public void createOperateLogV2(OperateLogV2CreateReqDTO createReqDTO) {
|
||||
OperateLogV2DO log = BeanUtils.toBean(createReqDTO, OperateLogV2DO.class);
|
||||
operateLogV2Mapper.insert(log);
|
||||
return operateLogMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<OperateLogV2DO> getOperateLogPage(OperateLogV2PageReqDTO pageReqDTO) {
|
||||
return operateLogV2Mapper.selectPage(pageReqDTO);
|
||||
public PageResult<OperateLogDO> getOperateLogPage(OperateLogPageReqDTO pageReqDTO) {
|
||||
return operateLogMapper.selectPage(pageReqDTO);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,35 +1,22 @@
|
||||
package cn.iocoder.yudao.module.system.service.logger;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogPageReqDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper;
|
||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
|
||||
import static cn.hutool.core.util.RandomUtil.randomEle;
|
||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@Import({OperateLogServiceImpl.class})
|
||||
public class OperateLogServiceImplTest extends BaseDbUnitTest {
|
||||
@ -40,13 +27,9 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest {
|
||||
@Resource
|
||||
private OperateLogMapper operateLogMapper;
|
||||
|
||||
@MockBean
|
||||
private AdminUserService userService;
|
||||
|
||||
@Test
|
||||
public void testCreateOperateLog() {
|
||||
OperateLogCreateReqDTO reqVO = RandomUtils.randomPojo(OperateLogCreateReqDTO.class,
|
||||
o -> o.setExts(MapUtil.<String, Object>builder("orderId", randomLongId()).build()));
|
||||
OperateLogCreateReqDTO reqVO = RandomUtils.randomPojo(OperateLogCreateReqDTO.class);
|
||||
|
||||
// 调研
|
||||
operateLogServiceImpl.createOperateLog(reqVO);
|
||||
@ -56,44 +39,38 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOperateLogPage() {
|
||||
// mock(用户信息)
|
||||
AdminUserDO user = RandomUtils.randomPojo(AdminUserDO.class, o -> {
|
||||
o.setNickname("wang");
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
});
|
||||
when(userService.getUserListByNickname("wang")).thenReturn(Collections.singletonList(user));
|
||||
Long userId = user.getId();
|
||||
|
||||
public void testGetOperateLogPage_vo() {
|
||||
// 构造操作日志
|
||||
OperateLogDO operateLogDO = RandomUtils.randomPojo(OperateLogDO.class, o -> {
|
||||
o.setUserId(userId);
|
||||
o.setUserType(randomEle(UserTypeEnum.values()).getValue());
|
||||
o.setModule("order");
|
||||
o.setType(OperateTypeEnum.CREATE.getType());
|
||||
o.setStartTime(buildTime(2021, 3, 6));
|
||||
o.setResultCode(GlobalErrorCodeConstants.SUCCESS.getCode());
|
||||
o.setExts(MapUtil.<String, Object>builder("orderId", randomLongId()).build());
|
||||
o.setUserId(2048L);
|
||||
o.setBizId(999L);
|
||||
o.setType("订单");
|
||||
o.setSubType("创建订单");
|
||||
o.setAction("修改编号为 1 的用户信息");
|
||||
o.setCreateTime(buildTime(2021, 3, 6));
|
||||
});
|
||||
operateLogMapper.insert(operateLogDO);
|
||||
// 测试 userId 不匹配
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setUserId(userId + 1)));
|
||||
// 测试 module 不匹配
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setModule("user")));
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setUserId(1024L)));
|
||||
// 测试 bizId 不匹配
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setBizId(888L)));
|
||||
// 测试 type 不匹配
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setType(OperateTypeEnum.IMPORT.getType())));
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setType("退款")));
|
||||
// 测试 subType 不匹配
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setSubType("创建退款")));
|
||||
// 测试 action 不匹配
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setAction("修改编号为 1 退款信息")));
|
||||
// 测试 createTime 不匹配
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setStartTime(buildTime(2021, 2, 6))));
|
||||
// 测试 resultCode 不匹配
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setResultCode(BAD_REQUEST.getCode())));
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setCreateTime(buildTime(2021, 2, 6))));
|
||||
|
||||
// 构造调用参数
|
||||
OperateLogPageReqVO reqVO = new OperateLogPageReqVO();
|
||||
reqVO.setUserNickname("wang");
|
||||
reqVO.setModule("order");
|
||||
reqVO.setType(OperateTypeEnum.CREATE.getType());
|
||||
reqVO.setStartTime(buildBetweenTime(2021, 3, 5, 2021, 3, 7));
|
||||
reqVO.setSuccess(true);
|
||||
reqVO.setUserId(2048L);
|
||||
reqVO.setBizId(999L);
|
||||
reqVO.setType("订");
|
||||
reqVO.setSubType("订单");
|
||||
reqVO.setAction("用户信息");
|
||||
reqVO.setCreateTime(buildBetweenTime(2021, 3, 5, 2021, 3, 7));
|
||||
|
||||
// 调用
|
||||
PageResult<OperateLogDO> pageResult = operateLogServiceImpl.getOperateLogPage(reqVO);
|
||||
@ -103,4 +80,34 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest {
|
||||
assertPojoEquals(operateLogDO, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOperateLogPage_dto() {
|
||||
// 构造操作日志
|
||||
OperateLogDO operateLogDO = RandomUtils.randomPojo(OperateLogDO.class, o -> {
|
||||
o.setUserId(2048L);
|
||||
o.setBizId(999L);
|
||||
o.setType("订单");
|
||||
});
|
||||
operateLogMapper.insert(operateLogDO);
|
||||
// 测试 userId 不匹配
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setUserId(1024L)));
|
||||
// 测试 bizId 不匹配
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setBizId(888L)));
|
||||
// 测试 type 不匹配
|
||||
operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setType("退款")));
|
||||
|
||||
// 构造调用参数
|
||||
OperateLogPageReqDTO reqDTO = new OperateLogPageReqDTO();
|
||||
reqDTO.setUserId(2048L);
|
||||
reqDTO.setBizId(999L);
|
||||
reqDTO.setType("订单");
|
||||
|
||||
// 调用
|
||||
PageResult<OperateLogDO> pageResult = operateLogServiceImpl.getOperateLogPage(reqDTO);
|
||||
// 断言,只查到了一条符合条件的
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(operateLogDO, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -202,22 +202,15 @@ CREATE TABLE IF NOT EXISTS `system_operate_log` (
|
||||
`trace_id` varchar(64) NOT NULL DEFAULT '',
|
||||
`user_id` bigint(20) NOT NULL,
|
||||
"user_type" tinyint not null default '0',
|
||||
`module` varchar(50) NOT NULL,
|
||||
`name` varchar(50) NOT NULL,
|
||||
`type` bigint(4) NOT NULL DEFAULT '0',
|
||||
`content` varchar(2000) NOT NULL DEFAULT '',
|
||||
`exts` varchar(512) NOT NULL DEFAULT '',
|
||||
`type` varchar(50) NOT NULL,
|
||||
`sub_type` varchar(50) NOT NULL,
|
||||
`biz_id` bigint(20) NOT NULL,
|
||||
`action` varchar(2000) NOT NULL DEFAULT '',
|
||||
`extra` varchar(512) NOT NULL DEFAULT '',
|
||||
`request_method` varchar(16) DEFAULT '',
|
||||
`request_url` varchar(255) DEFAULT '',
|
||||
`user_ip` varchar(50) DEFAULT NULL,
|
||||
`user_agent` varchar(200) DEFAULT NULL,
|
||||
`java_method` varchar(512) NOT NULL DEFAULT '',
|
||||
`java_method_args` varchar(8000) DEFAULT '',
|
||||
`start_time` datetime NOT NULL,
|
||||
`duration` int(11) NOT NULL,
|
||||
`result_code` int(11) NOT NULL DEFAULT '0',
|
||||
`result_msg` varchar(512) DEFAULT '',
|
||||
`result_data` varchar(4000) DEFAULT '',
|
||||
`creator` varchar(64) DEFAULT '',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updater` varchar(64) DEFAULT '',
|
||||
|
Reference in New Issue
Block a user