feat(sysapi): 重构接口日志查询支持动态表名与报文检索

- 替换Java硬编码查询为MyBatis XML动态SQL,支持动态切换日志表
- 新增请求报文与响应报文关键字搜索条件
- 前端字段映射由驼峰调整为下划线,适配Map返回结构
- 日志详情新增JSON一键复制功能与归档遮罩动画
This commit is contained in:
yangyufu
2026-07-03 14:15:50 +08:00
parent 8c71bf7965
commit 5bc0f50715
7 changed files with 318 additions and 115 deletions

View File

@@ -40,67 +40,12 @@ public class SysApiLogController {
private final ISysApiLogHistoryService apiLogHistoryService;
/**
* 分页查询接口日志列表
* 分页查询接口日志列表走XML动态SQL支持动态表名
*/
@GetMapping
@Log("查询接口日志列表")
public ResponseEntity<Map<String, Object>> query(ApiLogQuery query) {
LambdaQueryWrapper<SysApiLog> wrapper = new LambdaQueryWrapper<>();
if (query.getDirection() != null) {
wrapper.eq(SysApiLog::getDirection, query.getDirection());
}
if (query.getSystemFlag() != null && !query.getSystemFlag().isEmpty()) {
wrapper.eq(SysApiLog::getSystemFlag, query.getSystemFlag());
}
if (query.getBizCode() != null && !query.getBizCode().isEmpty()) {
wrapper.eq(SysApiLog::getBizCode, query.getBizCode());
}
if (query.getTraceId() != null && !query.getTraceId().isEmpty()) {
wrapper.eq(SysApiLog::getTraceId, query.getTraceId());
}
if (query.getApiUrl() != null && !query.getApiUrl().isEmpty()) {
wrapper.like(SysApiLog::getApiUrl, query.getApiUrl());
}
if (query.getStatus() != null && !query.getStatus().isEmpty()) {
wrapper.eq(SysApiLog::getStatus, query.getStatus());
}
if (query.getBegin_time() != null && !query.getBegin_time().isEmpty()) {
String beginTime = query.getBegin_time() + " 00:00:00";
wrapper.ge(SysApiLog::getCreateTime, beginTime);
}
if (query.getEnd_time() != null && !query.getEnd_time().isEmpty()) {
String endTime = query.getEnd_time() + " 23:59:59";
wrapper.le(SysApiLog::getCreateTime, endTime);
}
if (query.getKeyword() != null && !query.getKeyword().isEmpty()) {
wrapper.and(w -> w.like(SysApiLog::getBizDesc, query.getKeyword())
.or().like(SysApiLog::getApiDesc, query.getKeyword())
.or().like(SysApiLog::getRequestParams, query.getKeyword())
.or().like(SysApiLog::getResponseBody, query.getKeyword()));
}
wrapper.orderByDesc(SysApiLog::getCreateTime);
Page<SysApiLog> page = new Page<>(query.getPage()+1, query.getSize());
IPage<SysApiLog> result = apiLogService.page(page, wrapper);
Map<String, Object> response = new HashMap<>();
response.put("content", result.getRecords());
response.put("totalElements", result.getTotal());
response.put("totalPages", result.getPages());
response.put("size", result.getSize());
response.put("number", result.getCurrent());
return new ResponseEntity<>(response, HttpStatus.OK);
public ResponseEntity<Object> query(ApiLogQuery query) {
return new ResponseEntity<>(apiLogService.queryApiLog(query), HttpStatus.OK);
}
/**

View File

@@ -1,4 +1,5 @@
package org.nl.system.service.sysapi.entity.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import org.nl.common.domain.query.PageQuery;
@@ -30,5 +31,13 @@ public class ApiLogQuery extends PageQuery {
private String keyword;
private String requestParams;
private String responseParams;
/**
* 动态表名从前台传入sys_api_log 或 sys_api_log_history
*/
private String tableName;
}

View File

@@ -1,7 +1,12 @@
package org.nl.system.service.sysapi.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.nl.system.service.sysapi.entity.SysApiLog;
import org.nl.system.service.sysapi.entity.dto.ApiLogQuery;
import java.util.List;
import java.util.Map;
/**
* @author ManMan.Yang
@@ -13,4 +18,11 @@ import org.nl.system.service.sysapi.entity.SysApiLog;
@Mapper
public interface SysApiLogMapper extends BaseMapper<SysApiLog> {
/**
* 分页查询接口日志(动态表名)
* @param query 查询条件
* @return List<Map>
*/
List<Map> queryApiLog(@Param("query") ApiLogQuery query);
}

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.nl.system.service.sysapi.mapper.SysApiLogMapper">
<select id="queryApiLog" resultType="java.util.Map">
SELECT
t.log_id,
t.direction,
t.system_flag,
t.biz_code,
t.biz_desc,
t.api_url,
t.api_desc,
t.trace_id,
t.request_method,
t.request_ip,
t.request_headers,
t.request_params,
t.response_body,
t.response_status,
t.cost_time,
t.status,
t.error_msg,
t.operator,
t.create_time
FROM
${query.tableName} t
<where>
1 = 1
<if test="query.direction != null">
and t.direction = #{query.direction}
</if>
<if test="query.systemFlag != null and query.systemFlag != ''">
and t.system_flag = #{query.systemFlag}
</if>
<if test="query.bizCode != null and query.bizCode != ''">
and t.biz_code = #{query.bizCode}
</if>
<if test="query.traceId != null and query.traceId != ''">
and t.trace_id = #{query.traceId}
</if>
<if test="query.status != null and query.status != ''">
and t.status = #{query.status}
</if>
<if test="query.begin_time != null and query.begin_time != ''">
and t.create_time <![CDATA[ >= ]]> CONCAT(#{query.begin_time}, ' 00:00:00')
</if>
<if test="query.end_time != null and query.end_time != ''">
and t.create_time <![CDATA[ <= ]]> CONCAT(#{query.end_time}, ' 23:59:59')
</if>
<if test="query.requestParams != null and query.requestParams != ''">
and t.request_params LIKE CONCAT('%', #{query.requestParams}, '%')
</if>
<if test="query.responseParams != null and query.responseParams != ''">
and t.response_body LIKE CONCAT('%', #{query.responseParams}, '%')
</if>
</where>
ORDER BY t.create_time DESC
</select>
</mapper>

View File

@@ -2,9 +2,12 @@ package org.nl.system.service.sysapi.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.apache.poi.ss.formula.functions.T;
import org.nl.system.service.sysapi.entity.SysApiLog;
import org.nl.system.service.sysapi.entity.dto.ApiLogQuery;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import java.util.Map;
/**
* @author ManMan.Yang
* @version V1.1
@@ -18,4 +21,11 @@ public interface ISysApiLogService extends IService<SysApiLog> {
void saveAsync(SysApiLog apiLog);
ResponseEntity<T> archiveLogs();
/**
* 分页查询接口日志走XML动态SQL
* @param query 查询条件
* @return Object
*/
Object queryApiLog(ApiLogQuery query);
}

View File

@@ -3,13 +3,17 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.nl.common.TableDataInfo;
import org.nl.common.utils.IdUtil;
import org.nl.modules.wql.util.SpringContextHolder;
import org.nl.system.service.param.impl.SysParamServiceImpl;
import org.nl.system.service.sysapi.entity.SysApiLog;
import org.nl.system.service.sysapi.entity.SysApiLogHistory;
import org.nl.system.service.sysapi.entity.dto.ApiLogQuery;
import org.nl.system.service.sysapi.mapper.SysApiLogHistoryMapper;
import org.nl.system.service.sysapi.mapper.SysApiLogMapper;
import org.springframework.beans.factory.annotation.Autowired;
@@ -20,6 +24,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -91,4 +96,18 @@ public class SysApiLogServiceImpl extends ServiceImpl<SysApiLogMapper, SysApiLog
throw new RuntimeException("日志归档失败: " + e.getMessage());
}
}
@Override
public Object queryApiLog(ApiLogQuery query) {
// 默认查主表 sys_api_log
if (StrUtil.isEmpty(query.getTableName())) {
query.setTableName("sys_api_log");
}
// 使用 PageHelper 分页(排序已在 XML 中定义)
Page<Object> page = PageHelper.startPage(query.getPage() + 1, query.getSize());
List<Map> list = this.baseMapper.queryApiLog(query);
TableDataInfo<Map> build = TableDataInfo.build(list);
build.setTotalElements(page.getTotal());
return build;
}
}