Files
novalon-manage-system/DASHBOARD_ISSUE_DIAGNOSIS.md
T
张翔 31d66103e4 feat(登录日志): 添加今日登录次数统计功能
新增今日登录次数统计接口,修复Dashboard显示问题
- 在ISysLoginLogService接口添加countToday方法
- 实现SysLoginLogService中的countToday逻辑
- 更新ISysLoginLogRepository接口
- 添加SysLogHandler中的getTodayLoginCount方法
- 在SystemRouter中配置新路由端点

fix(测试): 更新系统配置URL匹配规则
- 将uat-phase1.spec.ts中的sysconfig改为sys/config

docs: 添加E2E测试报告和Dashboard问题诊断文档
2026-03-24 17:12:10 +08:00

301 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Dashboard数据显示问题诊断报告
## 问题描述
用户反馈Dashboard页面显示异常:
- 登录次数一直显示为0
- 操作日志一直显示为0
## 问题根因分析
### 1. 登录次数显示为0
**前端代码分析**[Dashboard.vue](file:///Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-web/src/views/system/Dashboard.vue#L127)):
```javascript
const todayLoginRes: any = await request.get('/logs/login/today/count')
stats.todayLogin = todayLoginRes || 0
```
**后端路由配置**[SystemRouter.java](file:///Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-app/src/main/java/cn/novalon/manage/app/config/SystemRouter.java#L139)):
```java
@Bean
public RouterFunction<ServerResponse> logRoutes(SysLogHandler logHandler) {
return route()
.GET("/api/logs/login", logHandler::getAllLoginLogs)
.GET("/api/logs/login/page", logHandler::getLoginLogsByPage)
.GET("/api/logs/login/count", logHandler::getLoginLogCount)
// 注意:缺少 /api/logs/login/today/count 端点
.build();
}
```
**服务接口分析**[ISysLoginLogService.java](file:///Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysLoginLogService.java)):
```java
public interface ISysLoginLogService {
Mono<SysLoginLog> findById(Long id);
Flux<SysLoginLog> findAll();
Flux<SysLoginLog> findByUsername(String username);
Flux<SysLoginLog> findByLoginTimeBetween(LocalDateTime startTime, LocalDateTime endTime);
Mono<SysLoginLog> save(SysLoginLog loginLog);
Mono<PageResponse<SysLoginLog>> findLoginLogsByPage(PageRequest pageRequest);
Mono<Long> count();
// 注意:缺少 countToday() 方法
}
```
**问题根因**
1. 前端请求 `/logs/login/today/count` 端点
2. 后端没有配置这个路由端点
3. `ISysLoginLogService` 接口缺少 `countToday()` 方法
4. 请求失败导致返回undefined,前端显示为0
### 2. 操作日志显示为0
**前端代码分析**[Dashboard.vue](file:///Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-web/src/views/system/Dashboard.vue#L131)):
```javascript
const operationLogRes: any = await request.get('/logs/operation/count')
stats.operationLog = operationLogRes || 0
```
**后端路由配置**[SystemRouter.java](file:///Users/zhangxiang/Codes/Novalon/novalon-manage-system/novalon-manage-api/manage-app/src/main/java/cn/novalon/manage/app/config/SystemRouter.java#L152)):
```java
@Bean
public RouterFunction<ServerResponse> operationLogRoutes(OperationLogHandler operationLogHandler) {
return route()
.GET("/api/logs/operation", operationLogHandler::getAllOperationLogs)
.GET("/api/logs/operation/page", operationLogHandler::getOperationLogsByPage)
.GET("/api/logs/operation/count", operationLogHandler::getOperationLogCount)
// 端点存在
.build();
}
```
**可能原因**
1. 数据库中确实没有操作日志记录
2. 操作日志拦截器可能没有正确记录日志
3. 统计查询可能有问题
## 修复方案
### 方案1:添加今日登录统计功能(推荐)
#### 1.1 更新服务接口
**文件**`ISysLoginLogService.java`
```java
public interface ISysLoginLogService {
Mono<SysLoginLog> findById(Long id);
Flux<SysLoginLog> findAll();
Flux<SysLoginLog> findByUsername(String username);
Flux<SysLoginLog> findByLoginTimeBetween(LocalDateTime startTime, LocalDateTime endTime);
Mono<SysLoginLog> save(SysLoginLog loginLog);
Mono<PageResponse<SysLoginLog>> findLoginLogsByPage(PageRequest pageRequest);
Mono<Long> count();
Mono<Long> countToday(); // 新增方法
}
```
#### 1.2 实现今日登录统计
**文件**`SysLoginLogService.java`
```java
@Override
public Mono<Long> countToday() {
LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
LocalDateTime todayEnd = todayStart.plusDays(1);
return repository.findByLoginTimeBetween(todayStart, todayEnd)
.count();
}
```
#### 1.3 添加Repository方法
**文件**`ISysLoginLogRepository.java`
```java
Flux<SysLoginLog> findByLoginTimeBetween(LocalDateTime startTime, LocalDateTime endTime);
```
#### 1.4 更新Handler
**文件**`SysLogHandler.java`
```java
@Operation(summary = "获取今日登录次数", description = "获取今日登录次数统计")
public Mono<ServerResponse> getTodayLoginCount(ServerRequest request) {
return loginLogService.countToday()
.flatMap(count -> ServerResponse.ok().bodyValue(count));
}
```
#### 1.5 更新路由配置
**文件**`SystemRouter.java`
```java
@Bean
public RouterFunction<ServerResponse> logRoutes(SysLogHandler logHandler) {
return route()
.GET("/api/logs/login", logHandler::getAllLoginLogs)
.GET("/api/logs/login/page", logHandler::getLoginLogsByPage)
.GET("/api/logs/login/count", logHandler::getLoginLogCount)
.GET("/api/logs/login/today/count", logHandler::getTodayLoginCount) // 新增路由
.build();
}
```
### 方案2:使用统一统计API(备选)
#### 2.1 更新前端Dashboard
**文件**`Dashboard.vue`
```javascript
const fetchStats = async () => {
loading.value = true
try {
// 使用统一的统计API
const statsRes: any = await request.get('/stats/overview')
stats.userCount = statsRes.userCount || 0
stats.roleCount = statsRes.roleCount || 0
stats.todayLogin = statsRes.todayOperationCount || 0 // 注意字段映射
stats.operationLog = statsRes.operationLogCount || 0
} catch (error) {
console.error('Failed to fetch stats:', error)
} finally {
loading.value = false
}
}
```
#### 2.2 更新StatsHandler
**文件**`StatsHandler.java`
```java
@Operation(summary = "获取系统概览", description = "获取系统统计概览信息")
public Mono<ServerResponse> getOverview(ServerRequest request) {
return Mono.zip(
userService.count(),
roleService.count(),
operationLogService.count(),
loginLogService.countToday(), // 添加今日登录统计
operationLogService.countToday()
).flatMap(tuple -> {
OverviewStats stats = new OverviewStats();
stats.setUserCount(tuple.getT1());
stats.setRoleCount(tuple.getT2());
stats.setOperationLogCount(tuple.getT3());
stats.setTodayLoginCount(tuple.getT4()); // 新增字段
stats.setTodayOperationCount(tuple.getT5());
return ServerResponse.ok().bodyValue(stats);
});
}
public static class OverviewStats {
private Long userCount;
private Long roleCount;
private Long operationLogCount;
private Long todayLoginCount; // 新增字段
private Long todayOperationCount;
// getters and setters...
}
```
### 方案3:检查操作日志记录
#### 3.1 检查操作日志拦截器
**文件**`OperationLogFilter.java`
确认拦截器是否正确配置和记录操作日志:
```java
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class OperationLogFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getPath().value();
// 排除不需要记录的路径
if (shouldSkipLogging(path)) {
return chain.filter(exchange);
}
// 记录操作日志
return chain.filter(exchange).doFinally(signalType -> {
OperationLog log = new OperationLog();
log.setUsername(getUsername(exchange));
log.setOperation(path);
log.setMethod(request.getMethod().name());
log.setIp(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
log.setStatus(exchange.getResponse().getStatusCode().value());
operationLogService.save(log).subscribe();
});
}
}
```
#### 3.2 验证数据库
```sql
-- 检查操作日志表是否有数据
SELECT COUNT(*) FROM operation_log;
-- 检查今日操作日志
SELECT COUNT(*) FROM operation_log
WHERE created_at >= CURRENT_DATE;
-- 检查最近10条操作日志
SELECT * FROM operation_log
ORDER BY created_at DESC
LIMIT 10;
```
## 推荐实施步骤
1. **立即修复**:实施方案1,添加今日登录统计功能
2. **验证操作日志**:检查操作日志拦截器和数据库记录
3. **长期优化**:考虑实施方案2,使用统一统计API简化前端逻辑
## 测试验证
修复后需要验证:
1. Dashboard页面正确显示今日登录次数
2. Dashboard页面正确显示操作日志数量
3. 执行一些操作后,操作日志数量增加
4. 登录后,今日登录次数增加
## 相关文件清单
需要修改的文件:
- `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/ISysLoginLogService.java`
- `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysLoginLogService.java`
- `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/repository/ISysLoginLogRepository.java`
- `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/log/SysLogHandler.java`
- `novalon-manage-api/manage-app/src/main/java/cn/novalon/manage/app/config/SystemRouter.java`
- `novalon-manage-web/src/views/system/Dashboard.vue`(可选,如果使用方案2
需要检查的文件:
- `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/interceptor/OperationLogFilter.java`
- 数据库表 `operation_log` 的数据记录情况