feat: 实现登录日志和操作日志的分页查询功能

refactor: 重构日志服务层代码,将分页逻辑移至Repository层

test: 添加日志分页查询的单元测试和组件测试

docs: 更新README文档,记录API响应格式修复过程

chore: 清理无用文件,更新.gitignore配置

build: 添加Jacoco代码覆盖率插件配置

ci: 添加测试环境配置文件application-h2-test.yml

style: 统一日志服务代码格式,添加必要的日志输出
This commit is contained in:
张翔
2026-04-03 17:49:55 +08:00
parent b0f91d74f5
commit 2de0529d34
36 changed files with 3549 additions and 462 deletions
@@ -2,6 +2,8 @@ package cn.novalon.manage.db.repository;
import cn.novalon.manage.sys.core.domain.SysExceptionLog;
import cn.novalon.manage.sys.core.repository.ISysExceptionLogRepository;
import cn.novalon.manage.common.dto.PageRequest;
import cn.novalon.manage.common.dto.PageResponse;
import cn.novalon.manage.db.converter.SysExceptionLogConverter;
import cn.novalon.manage.db.dao.SysExceptionLogDao;
import cn.novalon.manage.db.dao.QueryUtil;
@@ -16,6 +18,7 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.LocalDateTime;
import java.util.List;
/**
* 异常日志仓储实现类
@@ -89,4 +92,45 @@ public class SysExceptionLogRepository implements ISysExceptionLogRepository {
public Mono<Long> count() {
return sysExceptionLogDao.count();
}
@Override
public Mono<PageResponse<SysExceptionLog>> findExceptionLogsByPage(PageRequest pageRequest) {
int page = pageRequest.getPage();
int size = pageRequest.getSize();
String sort = pageRequest.getSort();
String order = pageRequest.getOrder();
String keyword = pageRequest.getKeyword();
SysExceptionLogQueryCriteria criteria = new SysExceptionLogQueryCriteria();
if (keyword != null && !keyword.isEmpty()) {
criteria.setKeyword(keyword);
}
Query queryObj = QueryUtil.getQuery(criteria);
Sort sortObj = Sort.unsorted();
if (sort != null && !sort.isEmpty()) {
sortObj = Sort.by(Sort.Direction.fromString(order), sort);
} else {
sortObj = Sort.by(Sort.Direction.DESC, "createTime");
}
org.springframework.data.domain.PageRequest pageable = org.springframework.data.domain.PageRequest.of(page,
size, sortObj);
return r2dbcEntityTemplate.select(SysExceptionLogEntity.class)
.matching(queryObj.with(pageable))
.all()
.collectList()
.zipWith(r2dbcEntityTemplate.count(queryObj, SysExceptionLogEntity.class))
.map(tuple -> {
long total = tuple.getT2();
int totalPages = (int) Math.ceil((double) total / size);
List<SysExceptionLog> logList = tuple.getT1().stream()
.map(sysExceptionLogConverter::toDomain)
.toList();
return new PageResponse<>(logList, totalPages, total, page, size);
});
}
}
@@ -2,6 +2,8 @@ package cn.novalon.manage.db.repository;
import cn.novalon.manage.sys.core.domain.SysLoginLog;
import cn.novalon.manage.sys.core.repository.ISysLoginLogRepository;
import cn.novalon.manage.common.dto.PageRequest;
import cn.novalon.manage.common.dto.PageResponse;
import cn.novalon.manage.db.converter.SysLoginLogConverter;
import cn.novalon.manage.db.dao.SysLoginLogDao;
import cn.novalon.manage.db.dao.QueryUtil;
@@ -16,6 +18,7 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.LocalDateTime;
import java.util.List;
/**
* 登录日志仓储实现类
@@ -94,4 +97,45 @@ public class SysLoginLogRepository implements ISysLoginLogRepository {
LocalDateTime todayEnd = todayStart.plusDays(1);
return findByLoginTimeBetweenOrderByLoginTimeDesc(todayStart, todayEnd).count();
}
@Override
public Mono<PageResponse<SysLoginLog>> findLoginLogsByPage(PageRequest pageRequest) {
int page = pageRequest.getPage();
int size = pageRequest.getSize();
String sort = pageRequest.getSort();
String order = pageRequest.getOrder();
String keyword = pageRequest.getKeyword();
SysLoginLogQueryCriteria criteria = new SysLoginLogQueryCriteria();
if (keyword != null && !keyword.isEmpty()) {
criteria.setKeyword(keyword);
}
Query queryObj = QueryUtil.getQuery(criteria);
Sort sortObj = Sort.unsorted();
if (sort != null && !sort.isEmpty()) {
sortObj = Sort.by(Sort.Direction.fromString(order), sort);
} else {
sortObj = Sort.by(Sort.Direction.DESC, "loginTime");
}
org.springframework.data.domain.PageRequest pageable = org.springframework.data.domain.PageRequest.of(page,
size, sortObj);
return r2dbcEntityTemplate.select(SysLoginLogEntity.class)
.matching(queryObj.with(pageable))
.all()
.collectList()
.zipWith(r2dbcEntityTemplate.count(queryObj, SysLoginLogEntity.class))
.map(tuple -> {
long total = tuple.getT2();
int totalPages = (int) Math.ceil((double) total / size);
List<SysLoginLog> logList = tuple.getT1().stream()
.map(sysLoginLogConverter::toDomain)
.toList();
return new PageResponse<>(logList, totalPages, total, page, size);
});
}
}