diff --git a/maku-boot-system/src/main/java/net/maku/system/controller/SysLogOperateController.java b/maku-boot-system/src/main/java/net/maku/system/controller/SysLogOperateController.java new file mode 100644 index 0000000..39beba1 --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/controller/SysLogOperateController.java @@ -0,0 +1,39 @@ +package net.maku.system.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.AllArgsConstructor; +import net.maku.framework.common.utils.PageResult; +import net.maku.framework.common.utils.Result; +import net.maku.system.query.SysLogOperateQuery; +import net.maku.system.service.SysLogOperateService; +import net.maku.system.vo.SysLogOperateVO; +import org.springdoc.core.annotations.ParameterObject; +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; + +/** + * 操作日志 + * + * @author 阿沐 babamu@126.com + * MAKU + */ +@RestController +@RequestMapping("sys/log/operate") +@Tag(name = "操作日志") +@AllArgsConstructor +public class SysLogOperateController { + private final SysLogOperateService sysLogOperateService; + + @GetMapping("page") + @Operation(summary = "分页") + @PreAuthorize("hasAuthority('sys:operate:all')") + public Result> page(@ParameterObject @Valid SysLogOperateQuery query) { + PageResult page = sysLogOperateService.page(query); + + return Result.ok(page); + } +} \ No newline at end of file diff --git a/maku-boot-system/src/main/java/net/maku/system/convert/SysLogOperateConvert.java b/maku-boot-system/src/main/java/net/maku/system/convert/SysLogOperateConvert.java new file mode 100644 index 0000000..6312b2e --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/convert/SysLogOperateConvert.java @@ -0,0 +1,26 @@ +package net.maku.system.convert; + +import net.maku.system.entity.SysLogOperateEntity; +import net.maku.system.vo.SysLogOperateVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 操作日志 + * + * @author 阿沐 babamu@126.com + * MAKU + */ +@Mapper +public interface SysLogOperateConvert { + SysLogOperateConvert INSTANCE = Mappers.getMapper(SysLogOperateConvert.class); + + SysLogOperateEntity convert(SysLogOperateVO vo); + + SysLogOperateVO convert(SysLogOperateEntity entity); + + List convertList(List list); + +} \ No newline at end of file diff --git a/maku-boot-system/src/main/java/net/maku/system/dao/SysLogOperateDao.java b/maku-boot-system/src/main/java/net/maku/system/dao/SysLogOperateDao.java new file mode 100644 index 0000000..7fe0d27 --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/dao/SysLogOperateDao.java @@ -0,0 +1,16 @@ +package net.maku.system.dao; + +import net.maku.framework.mybatis.dao.BaseDao; +import net.maku.system.entity.SysLogOperateEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 操作日志 + * + * @author 阿沐 babamu@126.com + * MAKU + */ +@Mapper +public interface SysLogOperateDao extends BaseDao { + +} \ No newline at end of file diff --git a/maku-boot-system/src/main/java/net/maku/system/entity/SysLogOperateEntity.java b/maku-boot-system/src/main/java/net/maku/system/entity/SysLogOperateEntity.java new file mode 100644 index 0000000..9b78b1d --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/entity/SysLogOperateEntity.java @@ -0,0 +1,103 @@ +package net.maku.system.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +/** + * 操作日志 + * + * @author 阿沐 babamu@126.com + * MAKU + */ + +@Data +@TableName("sys_log_operate") +public class SysLogOperateEntity { + /** + * id + */ + @TableId + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * 操作人 + */ + private String realName; + + /** + * 模块名 + */ + private String module; + + /** + * 操作名 + */ + private String name; + + /** + * 请求URI + */ + private String reqUri; + + /** + * 请求方法 + */ + private String reqMethod; + + /** + * 请求参数 + */ + private String reqParams; + + /** + * 操作IP + */ + private String ip; + + /** + * 登录地点 + */ + private String address; + + /** + * User Agent + */ + private String userAgent; + + /** + * 操作类型 + */ + private Integer operateType; + + /** + * 执行时长 + */ + private Integer duration; + + /** + * 操作状态 + */ + private Integer status; + + /** + * 返回消息 + */ + private String resultMsg; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private Date createTime; + +} \ No newline at end of file diff --git a/maku-boot-system/src/main/java/net/maku/system/query/SysLogOperateQuery.java b/maku-boot-system/src/main/java/net/maku/system/query/SysLogOperateQuery.java new file mode 100644 index 0000000..defdb50 --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/query/SysLogOperateQuery.java @@ -0,0 +1,30 @@ +package net.maku.system.query; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import net.maku.framework.common.query.Query; + +/** + * 操作日志查询 + * + * @author 阿沐 babamu@126.com + * MAKU + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Schema(description = "操作日志查询") +public class SysLogOperateQuery extends Query { + @Schema(description = "用户") + private String realName; + + @Schema(description = "模块名") + private String module; + + @Schema(description = "请求URI") + private String reqUri; + + @Schema(description = "操作状态") + private Integer status; + +} \ No newline at end of file diff --git a/maku-boot-system/src/main/java/net/maku/system/service/SysLogOperateService.java b/maku-boot-system/src/main/java/net/maku/system/service/SysLogOperateService.java new file mode 100644 index 0000000..5755813 --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/service/SysLogOperateService.java @@ -0,0 +1,18 @@ +package net.maku.system.service; + +import net.maku.framework.common.utils.PageResult; +import net.maku.framework.mybatis.service.BaseService; +import net.maku.system.entity.SysLogOperateEntity; +import net.maku.system.query.SysLogOperateQuery; +import net.maku.system.vo.SysLogOperateVO; + +/** + * 操作日志 + * + * @author 阿沐 babamu@126.com + * MAKU + */ +public interface SysLogOperateService extends BaseService { + + PageResult page(SysLogOperateQuery query); +} \ No newline at end of file diff --git a/maku-boot-system/src/main/java/net/maku/system/service/impl/SysLogOperateServiceImpl.java b/maku-boot-system/src/main/java/net/maku/system/service/impl/SysLogOperateServiceImpl.java new file mode 100644 index 0000000..be9b0e3 --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/service/impl/SysLogOperateServiceImpl.java @@ -0,0 +1,83 @@ +package net.maku.system.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import jakarta.annotation.PostConstruct; +import lombok.AllArgsConstructor; +import net.maku.framework.common.cache.RedisCache; +import net.maku.framework.common.cache.RedisKeys; +import net.maku.framework.common.utils.ExceptionUtils; +import net.maku.framework.common.utils.PageResult; +import net.maku.framework.mybatis.service.impl.BaseServiceImpl; +import net.maku.framework.operatelog.dto.OperateLogDTO; +import net.maku.system.convert.SysLogOperateConvert; +import net.maku.system.dao.SysLogOperateDao; +import net.maku.system.entity.SysLogOperateEntity; +import net.maku.system.query.SysLogOperateQuery; +import net.maku.system.service.SysLogOperateService; +import net.maku.system.vo.SysLogOperateVO; +import org.springframework.stereotype.Service; + +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * 操作日志 + * + * @author 阿沐 babamu@126.com + * MAKU + */ +@Service +@AllArgsConstructor +public class SysLogOperateServiceImpl extends BaseServiceImpl implements SysLogOperateService { + private final RedisCache redisCache; + + @Override + public PageResult page(SysLogOperateQuery query) { + IPage page = baseMapper.selectPage(getPage(query), getWrapper(query)); + + return new PageResult<>(SysLogOperateConvert.INSTANCE.convertList(page.getRecords()), page.getTotal()); + } + + private LambdaQueryWrapper getWrapper(SysLogOperateQuery query) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.eq(query.getStatus() != null, SysLogOperateEntity::getStatus, query.getStatus()); + wrapper.like(StrUtil.isNotBlank(query.getRealName()), SysLogOperateEntity::getRealName, query.getRealName()); + wrapper.like(StrUtil.isNotBlank(query.getModule()), SysLogOperateEntity::getModule, query.getModule()); + wrapper.like(StrUtil.isNotBlank(query.getReqUri()), SysLogOperateEntity::getReqUri, query.getReqUri()); + wrapper.orderByDesc(SysLogOperateEntity::getId); + return wrapper; + } + + /** + * 启动项目时,从Redis队列获取操作日志并保存 + */ + @PostConstruct + public void saveLog() { + ScheduledExecutorService scheduledService = ThreadUtil.createScheduledExecutor(1); + + // 每隔10秒钟,执行一次 + scheduledService.scheduleWithFixedDelay(() -> { + try { + String key = RedisKeys.getLogKey(); + // 每次插入10条 + int count = 10; + for (int i = 0; i < count; i++) { + OperateLogDTO log = (OperateLogDTO) redisCache.rightPop(key); + if (log == null) { + return; + } + + SysLogOperateEntity entity = BeanUtil.copyProperties(log, SysLogOperateEntity.class); + baseMapper.insert(entity); + } + } catch (Exception e) { + log.error("SysLogOperateServiceImpl.saveLog Error:" + ExceptionUtils.getExceptionMessage(e)); + } + }, 1, 10, TimeUnit.SECONDS); + } +} \ No newline at end of file diff --git a/maku-boot-system/src/main/java/net/maku/system/vo/SysLogOperateVO.java b/maku-boot-system/src/main/java/net/maku/system/vo/SysLogOperateVO.java new file mode 100644 index 0000000..c261f30 --- /dev/null +++ b/maku-boot-system/src/main/java/net/maku/system/vo/SysLogOperateVO.java @@ -0,0 +1,71 @@ +package net.maku.system.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.maku.framework.common.utils.DateUtils; + +import java.io.Serializable; +import java.util.Date; + +/** + * 操作日志 + * + * @author 阿沐 babamu@126.com + * MAKU + */ +@Data +@Schema(description = "操作日志") +public class SysLogOperateVO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(description = "id") + private Long id; + + @Schema(description = "用户ID") + private Long userId; + + @Schema(description = "操作人") + private String realName; + + @Schema(description = "模块名") + private String module; + + @Schema(description = "操作名") + private String name; + + @Schema(description = "请求URI") + private String reqUri; + + @Schema(description = "请求方法") + private String reqMethod; + + @Schema(description = "请求参数") + private String reqParams; + + @Schema(description = "操作IP") + private String ip; + + @Schema(description = "登录地点") + private String address; + + @Schema(description = "User Agent") + private String userAgent; + + @Schema(description = "操作类型") + private Integer operateType; + + @Schema(description = "执行时长") + private Integer duration; + + @Schema(description = "操作状态") + private Integer status; + + @Schema(description = "返回消息") + private String resultMsg; + + @Schema(description = "创建时间") + @JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN) + private Date createTime; + +} \ No newline at end of file diff --git a/maku-boot-system/src/main/resources/mapper/SysLogOperateDao.xml b/maku-boot-system/src/main/resources/mapper/SysLogOperateDao.xml new file mode 100644 index 0000000..d0fd093 --- /dev/null +++ b/maku-boot-system/src/main/resources/mapper/SysLogOperateDao.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file