添加操作日志
This commit is contained in:
@@ -157,6 +157,10 @@
|
||||
<groupId>org.xujun</groupId>
|
||||
<artifactId>xtools-app-sys-risk</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xujun</groupId>
|
||||
<artifactId>xtools-app-sys-tag</artifactId>
|
||||
</dependency>
|
||||
<!-- 项目模块 end -->
|
||||
|
||||
<!-- mapstruct begin -->
|
||||
|
||||
@@ -4,6 +4,9 @@ import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Title : SysConfig</p>
|
||||
* <p>Description : SysConfig</p>
|
||||
@@ -57,6 +60,11 @@ public class SysConfig {
|
||||
* 最大保存天数
|
||||
*/
|
||||
private int maxDays = 2;
|
||||
|
||||
/**
|
||||
* 忽略操作日志
|
||||
*/
|
||||
private List<String> ignoreOptLog = new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package xtools.app.sys.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import xtools.app.sys.model.dto.excel.SysOptLogExcel;
|
||||
import xtools.app.sys.model.dto.req.SysOptLogPageReq;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogResp;
|
||||
import xtools.app.sys.service.SysOptLogService;
|
||||
import xtools.boot.api.exection.BizError;
|
||||
import xtools.boot.api.model.dto.Result;
|
||||
import xtools.boot.api.model.dto.page.PageReq;
|
||||
import xtools.boot.api.model.dto.page.PageResp;
|
||||
import xtools.extend.office.FesodUtils;
|
||||
import xtools.web.HttpServletUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogController</p>
|
||||
* <p>Description : 系统操作日志 Controller</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-06-02 16:44:47
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "系统操作日志")
|
||||
@RestController
|
||||
@RequestMapping("/sys/opt-log")
|
||||
public class SysOptLogController {
|
||||
|
||||
private final SysOptLogService sysOptLogService;
|
||||
|
||||
@Operation(summary = "分页请求")
|
||||
@PostMapping("page")
|
||||
public Result<PageResp<SysOptLogResp>> page(@RequestBody @Valid PageReq<SysOptLogPageReq> pageReq) {
|
||||
return sysOptLogService.page(pageReq);
|
||||
}
|
||||
|
||||
@Operation(summary = "导出Excel")
|
||||
@PostMapping("export")
|
||||
public void exportExcel(@RequestBody @Valid SysOptLogPageReq req, HttpServletResponse response) {
|
||||
String sheetName = "系统操作日志";
|
||||
String filename = sheetName + ".xlsx";
|
||||
List<SysOptLogExcel> dataList = sysOptLogService.exportExcel(req);
|
||||
try {
|
||||
FesodUtils.write(response.getOutputStream(), SysOptLogExcel.class, sheetName, dataList);
|
||||
} catch (IOException e) {
|
||||
throw new BizError("导出Excel失败");
|
||||
}
|
||||
// 设置 header 和 contentType.写在最后的原因是,避免报错时,响应 contentType 已经被修改
|
||||
HttpServletUtils.addDownloadHeader(response, filename);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package xtools.app.sys.convert;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import xtools.app.sys.auth.model.dto.OptLogDto;
|
||||
import xtools.app.sys.model.dto.excel.SysOptLogExcel;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogResp;
|
||||
import xtools.app.sys.model.entity.SysOptLog;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogConvert</p>
|
||||
* <p>Description : 系统操作日志 Convert</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-06-02 16:44:47
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface SysOptLogConvert {
|
||||
|
||||
/**
|
||||
* 实体转响应
|
||||
*
|
||||
* @param data 实体
|
||||
* @return 响应
|
||||
*/
|
||||
SysOptLogResp entityToResp(SysOptLog data);
|
||||
|
||||
/**
|
||||
* 批量实体转响应
|
||||
*
|
||||
* @param dataList 批量实体
|
||||
* @return 响应
|
||||
*/
|
||||
List<SysOptLogResp> entityToRespList(List<SysOptLog> dataList);
|
||||
|
||||
/**
|
||||
* 实体转Excel
|
||||
*
|
||||
* @param data 实体
|
||||
* @return Excel
|
||||
*/
|
||||
SysOptLogExcel entityToExcel(SysOptLog data);
|
||||
|
||||
|
||||
/**
|
||||
* DTO转实体
|
||||
*
|
||||
* @param data DTO
|
||||
* @return 实体
|
||||
*/
|
||||
SysOptLog dtoToEntity(OptLogDto data);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package xtools.app.sys.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import xtools.app.sys.model.entity.SysOptLog;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogMapper</p>
|
||||
* <p>Description : 系统操作日志 Mapper 接口</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-06-02 16:44:47
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysOptLogMapper extends BaseMapper<SysOptLog> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package xtools.app.sys.model.dto.excel;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.fesod.sheet.annotation.ExcelProperty;
|
||||
import org.apache.fesod.sheet.annotation.format.DateTimeFormat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogExcel</p>
|
||||
* <p>Description : 系统操作日志Excel对象</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-06-02 16:44:47
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SysOptLogExcel implements Serializable {
|
||||
|
||||
/**
|
||||
* 日志追踪id
|
||||
*/
|
||||
@ExcelProperty("日志追踪id")
|
||||
private String traceId;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@ExcelProperty("标题")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 账号ID
|
||||
*/
|
||||
@ExcelProperty("账号ID")
|
||||
private Long accountId;
|
||||
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
@ExcelProperty("账号")
|
||||
private String account;
|
||||
|
||||
/**
|
||||
* IP
|
||||
*/
|
||||
@ExcelProperty("IP")
|
||||
private String ip;
|
||||
|
||||
/**
|
||||
* 地址
|
||||
*/
|
||||
@ExcelProperty("地址")
|
||||
private String addr;
|
||||
|
||||
/**
|
||||
* 操作URI
|
||||
*/
|
||||
@ExcelProperty("操作URI")
|
||||
private String uri;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty("备注")
|
||||
private String memo;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ExcelProperty("创建时间")
|
||||
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
|
||||
private Date gmtCreate;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package xtools.app.sys.model.dto.req;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogPageReq</p>
|
||||
* <p>Description : 系统操作日志分页请求对象</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-06-02 16:44:47
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SysOptLogPageReq implements Serializable {
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 日志追踪id
|
||||
*/
|
||||
@Schema(description = "日志追踪id")
|
||||
private String traceId;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 账号ID
|
||||
*/
|
||||
@Schema(description = "账号ID")
|
||||
private Long accountId;
|
||||
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
@Schema(description = "账号")
|
||||
private String account;
|
||||
|
||||
/**
|
||||
* IP
|
||||
*/
|
||||
@Schema(description = "IP")
|
||||
private String ip;
|
||||
|
||||
/**
|
||||
* 地址
|
||||
*/
|
||||
@Schema(description = "地址")
|
||||
private String addr;
|
||||
|
||||
/**
|
||||
* 地址code
|
||||
*/
|
||||
@Schema(description = "地址code")
|
||||
private String addrCode;
|
||||
|
||||
/**
|
||||
* 操作URI
|
||||
*/
|
||||
@Schema(description = "操作URI")
|
||||
private String uri;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@Schema(description = "备注")
|
||||
private String memo;
|
||||
|
||||
/**
|
||||
* 创建时间(范围)
|
||||
*/
|
||||
@Schema(description = "创建时间(范围)", example = "['2026-01-01 00:00:00', '2026-01-01 12:00:00']")
|
||||
private Instant[] gmtCreateRange;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package xtools.app.sys.model.dto.resp;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import xtools.boot.api.model.entity.BaseEntity;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogResp</p>
|
||||
* <p>Description : 系统操作日志响应对象</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-06-02 16:44:47
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SysOptLogResp extends BaseEntity {
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 日志追踪id
|
||||
*/
|
||||
@Schema(description = "日志追踪id")
|
||||
private String traceId;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 账号ID
|
||||
*/
|
||||
@Schema(description = "账号ID")
|
||||
private Long accountId;
|
||||
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
@Schema(description = "账号")
|
||||
private String account;
|
||||
|
||||
/**
|
||||
* IP
|
||||
*/
|
||||
@Schema(description = "IP")
|
||||
private String ip;
|
||||
|
||||
/**
|
||||
* 地址
|
||||
*/
|
||||
@Schema(description = "地址")
|
||||
private String addr;
|
||||
|
||||
/**
|
||||
* 地址code
|
||||
*/
|
||||
@Schema(description = "地址code")
|
||||
private String addrCode;
|
||||
|
||||
/**
|
||||
* 操作URI
|
||||
*/
|
||||
@Schema(description = "操作URI")
|
||||
private String uri;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@Schema(description = "备注")
|
||||
private String memo;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package xtools.app.sys.model.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLog</p>
|
||||
* <p>Description : 系统操作日志实体对象</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-06-02 16:44:47
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TableName("sys_opt_log")
|
||||
public class SysOptLog implements Serializable {
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 日志追踪id
|
||||
*/
|
||||
@Schema(description = "日志追踪id")
|
||||
@TableField(value = "trace_id")
|
||||
private String traceId;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@Schema(description = "标题")
|
||||
@TableField(value = "title")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 账号ID
|
||||
*/
|
||||
@Schema(description = "账号ID")
|
||||
@TableField(value = "account_id")
|
||||
private Long accountId;
|
||||
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
@Schema(description = "账号")
|
||||
@TableField(value = "account")
|
||||
private String account;
|
||||
|
||||
/**
|
||||
* IP
|
||||
*/
|
||||
@Schema(description = "IP")
|
||||
@TableField(value = "ip")
|
||||
private String ip;
|
||||
|
||||
/**
|
||||
* 地址
|
||||
*/
|
||||
@Schema(description = "地址")
|
||||
@TableField(value = "addr")
|
||||
private String addr;
|
||||
|
||||
/**
|
||||
* 地址code
|
||||
*/
|
||||
@Schema(description = "地址code")
|
||||
@TableField(value = "addr_code")
|
||||
private String addrCode;
|
||||
|
||||
/**
|
||||
* 操作URI
|
||||
*/
|
||||
@Schema(description = "操作URI")
|
||||
@TableField(value = "uri")
|
||||
private String uri;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@Schema(description = "备注")
|
||||
@TableField(value = "memo")
|
||||
private String memo;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(value = "gmt_create")
|
||||
@Schema(description = "创建时间", example = "2026-01-05 10:32:00")
|
||||
private Instant gmtCreate;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package xtools.app.sys.service;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import xtools.app.sys.model.dto.excel.SysOptLogExcel;
|
||||
import xtools.app.sys.model.dto.req.SysOptLogPageReq;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogResp;
|
||||
import xtools.boot.api.model.dto.Result;
|
||||
import xtools.boot.api.model.dto.page.PageReq;
|
||||
import xtools.boot.api.model.dto.page.PageResp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogService</p>
|
||||
* <p>Description : 系统操作日志 Service</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-06-02 16:44:47
|
||||
*/
|
||||
public interface SysOptLogService {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param pageReq 分页请求
|
||||
* @return 分页结果
|
||||
*/
|
||||
Result<PageResp<SysOptLogResp>> page(PageReq<SysOptLogPageReq> pageReq);
|
||||
|
||||
/**
|
||||
* 保存日志
|
||||
*
|
||||
* @param traceId 日志追踪 ID
|
||||
* @param logData 日志
|
||||
*/
|
||||
void save(String traceId, JSONObject logData);
|
||||
|
||||
/**
|
||||
* 导出 Excel
|
||||
*
|
||||
* @param req 请求参数
|
||||
* @return Excel 数据
|
||||
*/
|
||||
List<SysOptLogExcel> exportExcel(SysOptLogPageReq req);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package xtools.app.sys.service.base;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import xtools.app.sys.mapper.SysOptLogMapper;
|
||||
import xtools.app.sys.model.entity.SysOptLog;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogBaseService</p>
|
||||
* <p>Description : 系统操作日志 BaseService</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-06-02 16:44:47
|
||||
*/
|
||||
@Component
|
||||
public class SysOptLogBaseService extends ServiceImpl<SysOptLogMapper, SysOptLog> {
|
||||
}
|
||||
@@ -9,7 +9,9 @@ import org.springframework.stereotype.Service;
|
||||
import xtools.app.common.log.bus.service.LogBusService;
|
||||
import xtools.app.sys.model.entity.SysLog;
|
||||
import xtools.app.sys.service.SysLogService;
|
||||
import xtools.app.sys.service.SysOptLogService;
|
||||
import xtools.boot.api.model.dto.log.LogTrack;
|
||||
import xtools.boot.log.enums.LogBusBaseType;
|
||||
import xtools.boot.log.model.dto.LogBody;
|
||||
import xtools.boot.log.model.dto.RunInfo;
|
||||
import xtools.core.CollectionUtils;
|
||||
@@ -37,6 +39,8 @@ public class LogBusServiceImpl implements LogBusService {
|
||||
|
||||
private final SysLogService sysLogService;
|
||||
|
||||
private final SysOptLogService sysOptLogService;
|
||||
|
||||
/**
|
||||
* 保存日志
|
||||
*
|
||||
@@ -44,18 +48,25 @@ public class LogBusServiceImpl implements LogBusService {
|
||||
*/
|
||||
@Override
|
||||
public void saveLog(LogBody logBody) {
|
||||
LogTrack logTrack = logBody.getLogTrack();
|
||||
RunInfo runInfo = logBody.getRunInfo();
|
||||
// 获取日志类型
|
||||
String logType = logBody.getType();
|
||||
|
||||
LogTrack logTrack = logBody.getLogTrack();
|
||||
JSONObject logData = logBody.getLogData();
|
||||
if (CollectionUtils.isEmpty(logData)) {
|
||||
logData = new JSONObject();
|
||||
}
|
||||
|
||||
// 扩展日志处理
|
||||
if (extLog(logType, logTrack.traceId(), logData)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RunInfo runInfo = logBody.getRunInfo();
|
||||
JSONArray stackTrace = logBody.getStackTrace();
|
||||
|
||||
// 处理数据
|
||||
String title = logBody.getTitle();
|
||||
String logType = logBody.getType();
|
||||
title = StringUtils.isBlank(title) ? logType : title;
|
||||
// 获取请求ip
|
||||
String ip = logData.getString("ip");
|
||||
@@ -90,4 +101,20 @@ public class LogBusServiceImpl implements LogBusService {
|
||||
log.error("保存日志异常,logBody:{}", JsonUtils.toStrPretty(logBody), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 扩展日志
|
||||
*
|
||||
* @param logType 日志类型
|
||||
* @param traceId 日志追踪 ID
|
||||
* @param logData 日志数据
|
||||
* @return 保存结果
|
||||
*/
|
||||
private boolean extLog(String logType, String traceId, JSONObject logData) {
|
||||
if (LogBusBaseType.OPT_LOG.desc().equals(logType)) {
|
||||
sysOptLogService.save(traceId, logData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
package xtools.app.sys.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.stereotype.Service;
|
||||
import xtools.app.sys.auth.model.dto.OptLogDto;
|
||||
import xtools.app.sys.config.SysConfig;
|
||||
import xtools.app.sys.convert.SysOptLogConvert;
|
||||
import xtools.app.sys.model.dto.excel.SysOptLogExcel;
|
||||
import xtools.app.sys.model.dto.req.SysOptLogPageReq;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogResp;
|
||||
import xtools.app.sys.model.entity.SysOptLog;
|
||||
import xtools.app.sys.service.SysOptLogService;
|
||||
import xtools.app.sys.service.base.SysOptLogBaseService;
|
||||
import xtools.boot.api.model.dto.Result;
|
||||
import xtools.boot.api.model.dto.page.PageReq;
|
||||
import xtools.boot.api.model.dto.page.PageResp;
|
||||
import xtools.boot.core.utils.PathPatternUtils;
|
||||
import xtools.boot.db.mybatisplus.utils.QueryUtils;
|
||||
import xtools.boot.ip.utils.IpUtils;
|
||||
import xtools.core.StringUtils;
|
||||
import xtools.extend.dto.IpAddrDto;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogServiceImpl</p>
|
||||
* <p>Description : 系统操作日志 ServiceImpl</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-06-02 16:44:47
|
||||
*/
|
||||
@Slf4j
|
||||
@Primary
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SysOptLogServiceImpl implements SysOptLogService {
|
||||
|
||||
private final SysConfig sysConfig;
|
||||
|
||||
private final SysOptLogBaseService sysOptLogBaseService;
|
||||
|
||||
private final SysOptLogConvert sysOptLogConvert;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param pageReq 分页请求
|
||||
* @return 分页结果
|
||||
*/
|
||||
@Override
|
||||
public Result<PageResp<SysOptLogResp>> page(PageReq<SysOptLogPageReq> pageReq) {
|
||||
// 分页查询
|
||||
Page<SysOptLog> page = getPageData(pageReq.getCurrentPage(), pageReq.getPageSize(), pageReq.getQuery());
|
||||
// 分装结果
|
||||
PageResp<SysOptLogResp> pageResp = new PageResp<>(pageReq, page.getTotal(), sysOptLogConvert.entityToRespList(page.getRecords()));
|
||||
return Result.ok(pageResp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存日志
|
||||
*
|
||||
* @param traceId 日志追踪 ID
|
||||
* @param logData 日志
|
||||
*/
|
||||
@Override
|
||||
public void save(String traceId, JSONObject logData) {
|
||||
// 忽略操作日志
|
||||
List<String> ignoreOptLog = sysConfig.getLog().getIgnoreOptLog();
|
||||
|
||||
OptLogDto dto = logData.toJavaObject(OptLogDto.class);
|
||||
String uri = dto.getUri();
|
||||
|
||||
// 判断忽略操作日志
|
||||
if (PathPatternUtils.match(ignoreOptLog, uri)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dto.setTraceId(traceId);
|
||||
SysOptLog optLog = sysOptLogConvert.dtoToEntity(dto);
|
||||
String ip = optLog.getIp();
|
||||
if (StringUtils.isNotBlank(ip)) {
|
||||
try {
|
||||
IpAddrDto ipAddr = IpUtils.search(ip);
|
||||
optLog.setAddr(IpUtils.searchAddr(ipAddr));
|
||||
optLog.setAddrCode(IpUtils.getCode(ipAddr));
|
||||
} catch (Exception e) {
|
||||
log.warn("获取 IP 地址信息失败,IP = {}", ip);
|
||||
}
|
||||
}
|
||||
sysOptLogBaseService.save(optLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出 Excel
|
||||
*
|
||||
* @param req 请求参数
|
||||
* @return Excel 数据
|
||||
*/
|
||||
@Override
|
||||
public List<SysOptLogExcel> exportExcel(SysOptLogPageReq req) {
|
||||
// 创建查询条件
|
||||
LambdaQueryWrapper<SysOptLog> query = new LambdaQueryWrapper<>();
|
||||
// 查询字段
|
||||
query.select(
|
||||
SysOptLog::getTraceId
|
||||
, SysOptLog::getTitle
|
||||
, SysOptLog::getAccountId
|
||||
, SysOptLog::getAccount
|
||||
, SysOptLog::getIp
|
||||
, SysOptLog::getAddr
|
||||
, SysOptLog::getUri
|
||||
, SysOptLog::getMemo
|
||||
, SysOptLog::getGmtCreate
|
||||
);
|
||||
// 设置查询条件
|
||||
setQueryWrapper(query, req);
|
||||
// 排序
|
||||
query.orderByDesc(SysOptLog::getGmtCreate);
|
||||
List<SysOptLog> dataList = sysOptLogBaseService.list(query);
|
||||
return dataList.stream().map(sysOptLogConvert::entityToExcel).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分页数据
|
||||
*
|
||||
* @param currentPage 当前页
|
||||
* @param pageSize 每页数量
|
||||
* @param req 请求参数
|
||||
* @return 分页数据
|
||||
*/
|
||||
private Page<SysOptLog> getPageData(Integer currentPage, Integer pageSize, SysOptLogPageReq req) {
|
||||
// 创建查询条件
|
||||
LambdaQueryWrapper<SysOptLog> query = new LambdaQueryWrapper<>();
|
||||
// 查询字段
|
||||
query.select(
|
||||
SysOptLog::getId
|
||||
, SysOptLog::getTraceId
|
||||
, SysOptLog::getTitle
|
||||
, SysOptLog::getAccountId
|
||||
, SysOptLog::getAccount
|
||||
, SysOptLog::getIp
|
||||
, SysOptLog::getAddr
|
||||
, SysOptLog::getAddrCode
|
||||
, SysOptLog::getUri
|
||||
, SysOptLog::getMemo
|
||||
, SysOptLog::getGmtCreate
|
||||
);
|
||||
// 设置查询条件
|
||||
setQueryWrapper(query, req);
|
||||
// 排序
|
||||
query.orderByDesc(SysOptLog::getGmtCreate);
|
||||
return sysOptLogBaseService.page(QueryUtils.getPage(currentPage, pageSize), query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置查询条件
|
||||
*
|
||||
* @param query 查询条件
|
||||
* @param req 请求参数
|
||||
*/
|
||||
private void setQueryWrapper(LambdaQueryWrapper<SysOptLog> query, SysOptLogPageReq req) {
|
||||
if (Objects.isNull(req)) {
|
||||
return;
|
||||
}
|
||||
// 查询条件
|
||||
query.eq(Objects.nonNull(req.getId()), SysOptLog::getId, req.getId());
|
||||
query.like(StringUtils.isNotBlank(req.getTraceId()), SysOptLog::getTraceId, req.getTraceId());
|
||||
query.like(StringUtils.isNotBlank(req.getTitle()), SysOptLog::getTitle, req.getTitle());
|
||||
query.eq(Objects.nonNull(req.getAccountId()), SysOptLog::getAccountId, req.getAccountId());
|
||||
query.like(StringUtils.isNotBlank(req.getAccount()), SysOptLog::getAccount, req.getAccount());
|
||||
query.like(StringUtils.isNotBlank(req.getIp()), SysOptLog::getIp, req.getIp());
|
||||
query.like(StringUtils.isNotBlank(req.getAddr()), SysOptLog::getAddr, req.getAddr());
|
||||
query.like(StringUtils.isNotBlank(req.getAddrCode()), SysOptLog::getAddrCode, req.getAddrCode());
|
||||
query.like(StringUtils.isNotBlank(req.getUri()), SysOptLog::getUri, req.getUri());
|
||||
query.like(StringUtils.isNotBlank(req.getMemo()), SysOptLog::getMemo, req.getMemo());
|
||||
QueryUtils.addTimeRange(query, req.getGmtCreateRange(), SysOptLog::getGmtCreate);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user