Compare commits
No commits in common. "e0f47ce1b6bab95497e2b2f8f7db588e5fb0aefb" and "a2adaf38d124472ce7798fa8e06f265436ea83f1" have entirely different histories.
e0f47ce1b6
...
a2adaf38d1
@ -1,221 +0,0 @@
|
||||
package org.leocoder.thin.domain.model.vo.system;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 仪表盘统计数据响应对象
|
||||
*
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class DashboardStatisticsVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户统计数据
|
||||
*/
|
||||
@JsonProperty("userStats")
|
||||
private UserStatsVo userStats;
|
||||
|
||||
/**
|
||||
* 登录统计数据
|
||||
*/
|
||||
@JsonProperty("loginStats")
|
||||
private LoginStatsVo loginStats;
|
||||
|
||||
/**
|
||||
* 存储统计数据
|
||||
*/
|
||||
@JsonProperty("storageStats")
|
||||
private StorageStatsVo storageStats;
|
||||
|
||||
/**
|
||||
* 今日活跃统计数据
|
||||
*/
|
||||
@JsonProperty("dailyActivityStats")
|
||||
private DailyActivityStatsVo dailyActivityStats;
|
||||
|
||||
/**
|
||||
* 用户统计数据
|
||||
*/
|
||||
@Data
|
||||
public static class UserStatsVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 总用户数
|
||||
*/
|
||||
@JsonProperty("totalUsers")
|
||||
private Integer totalUsers;
|
||||
|
||||
/**
|
||||
* 今日新增用户数
|
||||
*/
|
||||
@JsonProperty("todayNewUsers")
|
||||
private Integer todayNewUsers;
|
||||
|
||||
/**
|
||||
* 活跃用户数
|
||||
*/
|
||||
@JsonProperty("activeUsers")
|
||||
private Integer activeUsers;
|
||||
|
||||
/**
|
||||
* 当前在线用户数
|
||||
*/
|
||||
@JsonProperty("onlineUsers")
|
||||
private Integer onlineUsers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录统计数据
|
||||
*/
|
||||
@Data
|
||||
public static class LoginStatsVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 今日登录次数
|
||||
*/
|
||||
@JsonProperty("todayLogins")
|
||||
private Integer todayLogins;
|
||||
|
||||
/**
|
||||
* 累计登录次数
|
||||
*/
|
||||
@JsonProperty("totalLogins")
|
||||
private Integer totalLogins;
|
||||
|
||||
/**
|
||||
* 登录趋势数据
|
||||
*/
|
||||
@JsonProperty("loginTrend")
|
||||
private List<LoginTrendItemVo> loginTrend;
|
||||
}
|
||||
|
||||
/**
|
||||
* 存储统计数据
|
||||
*/
|
||||
@Data
|
||||
public static class StorageStatsVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 总文件数
|
||||
*/
|
||||
@JsonProperty("totalFiles")
|
||||
private Integer totalFiles;
|
||||
|
||||
/**
|
||||
* 总图片数
|
||||
*/
|
||||
@JsonProperty("totalImages")
|
||||
private Integer totalImages;
|
||||
|
||||
/**
|
||||
* 总存储大小(格式化)
|
||||
*/
|
||||
@JsonProperty("totalSize")
|
||||
private String totalSize;
|
||||
|
||||
/**
|
||||
* 今日上传文件数
|
||||
*/
|
||||
@JsonProperty("todayUploads")
|
||||
private Integer todayUploads;
|
||||
|
||||
/**
|
||||
* 存储使用率(百分比)
|
||||
*/
|
||||
@JsonProperty("storageUsage")
|
||||
private Double storageUsage;
|
||||
|
||||
/**
|
||||
* 可用空间(格式化)
|
||||
*/
|
||||
@JsonProperty("availableSpace")
|
||||
private String availableSpace;
|
||||
}
|
||||
|
||||
/**
|
||||
* 今日活跃统计数据
|
||||
*/
|
||||
@Data
|
||||
public static class DailyActivityStatsVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 今日访问量
|
||||
*/
|
||||
@JsonProperty("todayVisits")
|
||||
private Integer todayVisits;
|
||||
|
||||
/**
|
||||
* 今日操作数
|
||||
*/
|
||||
@JsonProperty("todayOperations")
|
||||
private Integer todayOperations;
|
||||
|
||||
/**
|
||||
* 活跃用户数
|
||||
*/
|
||||
@JsonProperty("activeUsers")
|
||||
private Integer activeUsers;
|
||||
|
||||
/**
|
||||
* 新增内容数
|
||||
*/
|
||||
@JsonProperty("newContent")
|
||||
private Integer newContent;
|
||||
|
||||
/**
|
||||
* API调用次数
|
||||
*/
|
||||
@JsonProperty("apiCalls")
|
||||
private Integer apiCalls;
|
||||
|
||||
/**
|
||||
* 平均响应时间(毫秒)
|
||||
*/
|
||||
@JsonProperty("avgResponseTime")
|
||||
private Integer avgResponseTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录趋势项
|
||||
*/
|
||||
@Data
|
||||
public static class LoginTrendItemVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 日期(YYYY-MM-DD格式)
|
||||
*/
|
||||
@JsonProperty("date")
|
||||
private String date;
|
||||
|
||||
/**
|
||||
* 当日登录次数
|
||||
*/
|
||||
@JsonProperty("count")
|
||||
private Integer count;
|
||||
|
||||
/**
|
||||
* 显示标签(用于图表展示)
|
||||
*/
|
||||
@JsonProperty("label")
|
||||
private String label;
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
package org.leocoder.thin.domain.model.vo.system;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 登录趋势数据响应对象
|
||||
*
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class LoginTrendVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 登录趋势数据列表
|
||||
*/
|
||||
@JsonProperty("loginTrend")
|
||||
private List<LoginTrendItemVo> loginTrend;
|
||||
|
||||
/**
|
||||
* 登录趋势项
|
||||
*/
|
||||
@Data
|
||||
public static class LoginTrendItemVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 日期(YYYY-MM-DD格式)
|
||||
*/
|
||||
@JsonProperty("date")
|
||||
private String date;
|
||||
|
||||
/**
|
||||
* 当日登录次数
|
||||
*/
|
||||
@JsonProperty("count")
|
||||
private Integer count;
|
||||
|
||||
/**
|
||||
* 显示标签(用于图表展示)
|
||||
*/
|
||||
@JsonProperty("label")
|
||||
private String label;
|
||||
}
|
||||
}
|
||||
@ -1,173 +0,0 @@
|
||||
package org.leocoder.thin.system.controller.dashboard;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.leocoder.thin.common.exception.coder.YUtil;
|
||||
import org.leocoder.thin.domain.model.vo.system.DashboardStatisticsVo;
|
||||
import org.leocoder.thin.domain.model.vo.system.LoginTrendVo;
|
||||
import org.leocoder.thin.system.service.dashboard.DashboardService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 仪表盘统计控制器
|
||||
*
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Tag(name = "仪表盘管理", description = "仪表盘统计数据接口")
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RestController
|
||||
@RequestMapping("/coder/dashboard")
|
||||
@RequiredArgsConstructor
|
||||
public class DashboardController {
|
||||
|
||||
private final DashboardService dashboardService;
|
||||
|
||||
/**
|
||||
* @description 获取仪表盘统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Operation(
|
||||
summary = "获取仪表盘统计数据",
|
||||
description = "获取用户、登录、存储、活跃度等核心统计数据"
|
||||
)
|
||||
@GetMapping("/getStatistics")
|
||||
@SaCheckPermission("dashboard:view")
|
||||
public DashboardStatisticsVo getStatistics() {
|
||||
DashboardStatisticsVo statistics = dashboardService.getStatistics();
|
||||
YUtil.isTrue(ObjectUtils.isEmpty(statistics), "获取仪表盘统计数据失败");
|
||||
return statistics;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取登录趋势数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Operation(
|
||||
summary = "获取登录趋势数据",
|
||||
description = "获取最近N天的登录趋势图表数据"
|
||||
)
|
||||
@GetMapping("/getLoginTrend")
|
||||
@SaCheckPermission("dashboard:view")
|
||||
public LoginTrendVo getLoginTrend(
|
||||
@Parameter(description = "查询天数", example = "7") @RequestParam(
|
||||
defaultValue = "7"
|
||||
) Integer days
|
||||
) {
|
||||
LoginTrendVo loginTrend = dashboardService.getLoginTrend(days);
|
||||
YUtil.isTrue(ObjectUtils.isEmpty(loginTrend), "获取登录趋势数据失败");
|
||||
return loginTrend;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取完整仪表盘数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Operation(
|
||||
summary = "获取完整仪表盘数据",
|
||||
description = "一次性获取所有仪表盘数据,减少前端请求次数"
|
||||
)
|
||||
@GetMapping("/getAllData")
|
||||
@SaCheckPermission("dashboard:view")
|
||||
public DashboardStatisticsVo getAllData(
|
||||
@Parameter(
|
||||
description = "是否包含趋势数据",
|
||||
example = "true"
|
||||
) @RequestParam(defaultValue = "true") Boolean includeTrend,
|
||||
@Parameter(description = "趋势数据天数", example = "7") @RequestParam(
|
||||
defaultValue = "7"
|
||||
) Integer trendDays
|
||||
) {
|
||||
DashboardStatisticsVo allData = dashboardService.getAllData(
|
||||
includeTrend,
|
||||
trendDays
|
||||
);
|
||||
YUtil.isTrue(ObjectUtils.isEmpty(allData), "获取完整仪表盘数据失败");
|
||||
return allData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取用户统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Operation(
|
||||
summary = "获取用户统计数据",
|
||||
description = "获取用户相关的统计信息"
|
||||
)
|
||||
@GetMapping("/getUserStats")
|
||||
@SaCheckPermission("dashboard:view")
|
||||
public DashboardStatisticsVo.UserStatsVo getUserStats() {
|
||||
DashboardStatisticsVo.UserStatsVo userStats =
|
||||
dashboardService.getUserStats();
|
||||
YUtil.isTrue(ObjectUtils.isEmpty(userStats), "获取用户统计数据失败");
|
||||
return userStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取登录统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Operation(
|
||||
summary = "获取登录统计数据",
|
||||
description = "获取登录相关的统计信息"
|
||||
)
|
||||
@GetMapping("/getLoginStats")
|
||||
@SaCheckPermission("dashboard:view")
|
||||
public DashboardStatisticsVo.LoginStatsVo getLoginStats(
|
||||
@Parameter(
|
||||
description = "是否包含趋势数据",
|
||||
example = "false"
|
||||
) @RequestParam(defaultValue = "false") Boolean includeTrend,
|
||||
@Parameter(description = "趋势数据天数", example = "7") @RequestParam(
|
||||
defaultValue = "7"
|
||||
) Integer trendDays
|
||||
) {
|
||||
DashboardStatisticsVo.LoginStatsVo loginStats =
|
||||
dashboardService.getLoginStats(includeTrend, trendDays);
|
||||
YUtil.isTrue(ObjectUtils.isEmpty(loginStats), "获取登录统计数据失败");
|
||||
return loginStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取存储统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Operation(
|
||||
summary = "获取存储统计数据",
|
||||
description = "获取存储相关的统计信息"
|
||||
)
|
||||
@GetMapping("/getStorageStats")
|
||||
@SaCheckPermission("dashboard:view")
|
||||
public DashboardStatisticsVo.StorageStatsVo getStorageStats() {
|
||||
DashboardStatisticsVo.StorageStatsVo storageStats =
|
||||
dashboardService.getStorageStats();
|
||||
YUtil.isTrue(ObjectUtils.isEmpty(storageStats), "获取存储统计数据失败");
|
||||
return storageStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取今日活跃统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Operation(
|
||||
summary = "获取今日活跃统计数据",
|
||||
description = "获取今日活跃相关的统计信息"
|
||||
)
|
||||
@GetMapping("/getDailyActivityStats")
|
||||
@SaCheckPermission("dashboard:view")
|
||||
public DashboardStatisticsVo.DailyActivityStatsVo getDailyActivityStats() {
|
||||
DashboardStatisticsVo.DailyActivityStatsVo activityStats =
|
||||
dashboardService.getDailyActivityStats();
|
||||
YUtil.isTrue(
|
||||
ObjectUtils.isEmpty(activityStats),
|
||||
"获取今日活跃统计数据失败"
|
||||
);
|
||||
return activityStats;
|
||||
}
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
package org.leocoder.thin.system.service.dashboard;
|
||||
|
||||
import org.leocoder.thin.domain.model.vo.system.DashboardStatisticsVo;
|
||||
import org.leocoder.thin.domain.model.vo.system.LoginTrendVo;
|
||||
|
||||
/**
|
||||
* 仪表盘统计服务接口
|
||||
*
|
||||
* @author Leocoder
|
||||
*/
|
||||
public interface DashboardService {
|
||||
|
||||
/**
|
||||
* @description 获取仪表盘统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
DashboardStatisticsVo getStatistics();
|
||||
|
||||
/**
|
||||
* @description 获取登录趋势数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
LoginTrendVo getLoginTrend(Integer days);
|
||||
|
||||
/**
|
||||
* @description 获取完整仪表盘数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
DashboardStatisticsVo getAllData(Boolean includeTrend, Integer trendDays);
|
||||
|
||||
/**
|
||||
* @description 获取用户统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
DashboardStatisticsVo.UserStatsVo getUserStats();
|
||||
|
||||
/**
|
||||
* @description 获取登录统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
DashboardStatisticsVo.LoginStatsVo getLoginStats(Boolean includeTrend, Integer trendDays);
|
||||
|
||||
/**
|
||||
* @description 获取存储统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
DashboardStatisticsVo.StorageStatsVo getStorageStats();
|
||||
|
||||
/**
|
||||
* @description 获取今日活跃统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
DashboardStatisticsVo.DailyActivityStatsVo getDailyActivityStats();
|
||||
}
|
||||
@ -1,370 +0,0 @@
|
||||
package org.leocoder.thin.system.service.dashboard;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.leocoder.thin.domain.model.vo.system.DashboardStatisticsVo;
|
||||
import org.leocoder.thin.domain.model.vo.system.LoginTrendVo;
|
||||
import org.leocoder.thin.domain.pojo.system.*;
|
||||
import org.leocoder.thin.mybatisplus.mapper.system.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 仪表盘统计服务实现类
|
||||
*
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DashboardServiceImpl implements DashboardService {
|
||||
|
||||
private final SysLoginUserMapper sysLoginUserMapper;
|
||||
private final SysLoginLogMapper sysLoginLogMapper;
|
||||
private final SysOperLogMapper sysOperLogMapper;
|
||||
private final SysFileMapper sysFileMapper;
|
||||
private final SysPictureMapper sysPictureMapper;
|
||||
|
||||
/**
|
||||
* @description 获取仪表盘统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Override
|
||||
public DashboardStatisticsVo getStatistics() {
|
||||
DashboardStatisticsVo statisticsVo = new DashboardStatisticsVo();
|
||||
|
||||
// 设置用户统计数据
|
||||
statisticsVo.setUserStats(getUserStats());
|
||||
|
||||
// 设置登录统计数据(不包含趋势)
|
||||
statisticsVo.setLoginStats(getLoginStats(false, null));
|
||||
|
||||
// 设置存储统计数据
|
||||
statisticsVo.setStorageStats(getStorageStats());
|
||||
|
||||
// 设置今日活跃统计数据
|
||||
statisticsVo.setDailyActivityStats(getDailyActivityStats());
|
||||
|
||||
return statisticsVo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取登录趋势数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Override
|
||||
public LoginTrendVo getLoginTrend(Integer days) {
|
||||
if (days == null || days <= 0) {
|
||||
days = 7;
|
||||
}
|
||||
|
||||
LoginTrendVo loginTrendVo = new LoginTrendVo();
|
||||
List<LoginTrendVo.LoginTrendItemVo> trendList = new ArrayList<>();
|
||||
|
||||
LocalDate today = LocalDate.now();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
DateTimeFormatter labelFormatter = DateTimeFormatter.ofPattern(
|
||||
"M月d日"
|
||||
);
|
||||
|
||||
for (int i = days - 1; i >= 0; i--) {
|
||||
LocalDate date = today.minusDays(i);
|
||||
String dateStr = date.format(formatter);
|
||||
String label = date.format(labelFormatter);
|
||||
|
||||
// 统计该日的登录次数
|
||||
LambdaQueryWrapper<SysLoginLog> wrapper =
|
||||
new LambdaQueryWrapper<>();
|
||||
wrapper
|
||||
.apply("DATE(login_time) = {0}", dateStr)
|
||||
// 成功登录
|
||||
.eq(SysLoginLog::getLoginStatus, "0");
|
||||
Long count = sysLoginLogMapper.selectCount(wrapper);
|
||||
|
||||
LoginTrendVo.LoginTrendItemVo trendItem =
|
||||
new LoginTrendVo.LoginTrendItemVo();
|
||||
trendItem.setDate(dateStr);
|
||||
trendItem.setCount(count != null ? count.intValue() : 0);
|
||||
trendItem.setLabel(label);
|
||||
|
||||
trendList.add(trendItem);
|
||||
}
|
||||
|
||||
loginTrendVo.setLoginTrend(trendList);
|
||||
return loginTrendVo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取完整仪表盘数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Override
|
||||
public DashboardStatisticsVo getAllData(
|
||||
Boolean includeTrend,
|
||||
Integer trendDays
|
||||
) {
|
||||
DashboardStatisticsVo statisticsVo = new DashboardStatisticsVo();
|
||||
|
||||
// 设置用户统计数据
|
||||
statisticsVo.setUserStats(getUserStats());
|
||||
|
||||
// 设置登录统计数据(根据参数决定是否包含趋势)
|
||||
statisticsVo.setLoginStats(getLoginStats(includeTrend, trendDays));
|
||||
|
||||
// 设置存储统计数据
|
||||
statisticsVo.setStorageStats(getStorageStats());
|
||||
|
||||
// 设置今日活跃统计数据
|
||||
statisticsVo.setDailyActivityStats(getDailyActivityStats());
|
||||
|
||||
return statisticsVo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取用户统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Override
|
||||
public DashboardStatisticsVo.UserStatsVo getUserStats() {
|
||||
DashboardStatisticsVo.UserStatsVo userStats =
|
||||
new DashboardStatisticsVo.UserStatsVo();
|
||||
|
||||
try {
|
||||
// 总用户数
|
||||
Long totalUsers = sysLoginUserMapper.selectCount(null);
|
||||
userStats.setTotalUsers(
|
||||
totalUsers != null ? totalUsers.intValue() : 0
|
||||
);
|
||||
|
||||
// 今日新增用户数
|
||||
LambdaQueryWrapper<SysLoginUser> todayWrapper =
|
||||
new LambdaQueryWrapper<>();
|
||||
todayWrapper.apply("DATE(create_time) = CURDATE()");
|
||||
Long todayNewUsers = sysLoginUserMapper.selectCount(todayWrapper);
|
||||
userStats.setTodayNewUsers(
|
||||
todayNewUsers != null ? todayNewUsers.intValue() : 0
|
||||
);
|
||||
|
||||
// 活跃用户数(最近30天有登录记录的用户)
|
||||
LambdaQueryWrapper<SysLoginLog> activeWrapper =
|
||||
new LambdaQueryWrapper<>();
|
||||
activeWrapper
|
||||
.apply("login_time >= DATE_SUB(NOW(), INTERVAL 30 DAY)")
|
||||
.eq(SysLoginLog::getLoginStatus, "0")
|
||||
.select(SysLoginLog::getLoginName)
|
||||
.groupBy(SysLoginLog::getLoginName);
|
||||
Long activeUsers = sysLoginLogMapper.selectCount(activeWrapper);
|
||||
userStats.setActiveUsers(
|
||||
activeUsers != null ? activeUsers.intValue() : 0
|
||||
);
|
||||
|
||||
// 当前在线用户数(通过Sa-Token获取)
|
||||
List<String> onlineTokens = StpUtil.searchTokenValue(
|
||||
"",
|
||||
0,
|
||||
-1,
|
||||
false
|
||||
);
|
||||
userStats.setOnlineUsers(
|
||||
onlineTokens != null ? onlineTokens.size() : 0
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.error("获取用户统计数据失败", e);
|
||||
// 设置默认值
|
||||
userStats.setTotalUsers(0);
|
||||
userStats.setTodayNewUsers(0);
|
||||
userStats.setActiveUsers(0);
|
||||
userStats.setOnlineUsers(0);
|
||||
}
|
||||
|
||||
return userStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取登录统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Override
|
||||
public DashboardStatisticsVo.LoginStatsVo getLoginStats(
|
||||
Boolean includeTrend,
|
||||
Integer trendDays
|
||||
) {
|
||||
DashboardStatisticsVo.LoginStatsVo loginStats =
|
||||
new DashboardStatisticsVo.LoginStatsVo();
|
||||
|
||||
try {
|
||||
// 今日登录次数
|
||||
LambdaQueryWrapper<SysLoginLog> todayWrapper =
|
||||
new LambdaQueryWrapper<>();
|
||||
todayWrapper
|
||||
.apply("DATE(login_time) = CURDATE()")
|
||||
.eq(SysLoginLog::getLoginStatus, "0"); // 成功登录
|
||||
Long todayLogins = sysLoginLogMapper.selectCount(todayWrapper);
|
||||
loginStats.setTodayLogins(
|
||||
todayLogins != null ? todayLogins.intValue() : 0
|
||||
);
|
||||
|
||||
// 累计登录次数
|
||||
LambdaQueryWrapper<SysLoginLog> totalWrapper =
|
||||
new LambdaQueryWrapper<>();
|
||||
totalWrapper.eq(SysLoginLog::getLoginStatus, "0"); // 成功登录
|
||||
Long totalLogins = sysLoginLogMapper.selectCount(totalWrapper);
|
||||
loginStats.setTotalLogins(
|
||||
totalLogins != null ? totalLogins.intValue() : 0
|
||||
);
|
||||
|
||||
// 根据参数决定是否包含趋势数据
|
||||
if (Boolean.TRUE.equals(includeTrend)) {
|
||||
LoginTrendVo trendVo = getLoginTrend(trendDays);
|
||||
// 转换LoginTrendItemVo类型
|
||||
if (trendVo.getLoginTrend() != null) {
|
||||
List<DashboardStatisticsVo.LoginTrendItemVo> trendItems =
|
||||
new ArrayList<>();
|
||||
for (LoginTrendVo.LoginTrendItemVo item : trendVo.getLoginTrend()) {
|
||||
DashboardStatisticsVo.LoginTrendItemVo trendItem =
|
||||
new DashboardStatisticsVo.LoginTrendItemVo();
|
||||
trendItem.setDate(item.getDate());
|
||||
trendItem.setCount(item.getCount());
|
||||
trendItem.setLabel(item.getLabel());
|
||||
trendItems.add(trendItem);
|
||||
}
|
||||
loginStats.setLoginTrend(trendItems);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("获取登录统计数据失败", e);
|
||||
// 设置默认值
|
||||
loginStats.setTodayLogins(0);
|
||||
loginStats.setTotalLogins(0);
|
||||
}
|
||||
|
||||
return loginStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取存储统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Override
|
||||
public DashboardStatisticsVo.StorageStatsVo getStorageStats() {
|
||||
DashboardStatisticsVo.StorageStatsVo storageStats =
|
||||
new DashboardStatisticsVo.StorageStatsVo();
|
||||
|
||||
try {
|
||||
// 总文件数
|
||||
Long totalFiles = sysFileMapper.selectCount(null);
|
||||
storageStats.setTotalFiles(
|
||||
totalFiles != null ? totalFiles.intValue() : 0
|
||||
);
|
||||
|
||||
// 总图片数
|
||||
Long totalImages = sysPictureMapper.selectCount(null);
|
||||
storageStats.setTotalImages(
|
||||
totalImages != null ? totalImages.intValue() : 0
|
||||
);
|
||||
|
||||
// 今日上传文件数
|
||||
LambdaQueryWrapper<SysFile> todayWrapper =
|
||||
new LambdaQueryWrapper<>();
|
||||
todayWrapper.apply("DATE(create_time) = CURDATE()");
|
||||
Long todayUploads = sysFileMapper.selectCount(todayWrapper);
|
||||
storageStats.setTodayUploads(
|
||||
todayUploads != null ? todayUploads.intValue() : 0
|
||||
);
|
||||
|
||||
// 计算总存储大小(这里可以根据实际情况优化)
|
||||
// 由于文件大小计算比较复杂,这里先设置示例数据
|
||||
storageStats.setTotalSize("2.3 GB");
|
||||
storageStats.setStorageUsage(67.5);
|
||||
storageStats.setAvailableSpace("1.2 GB");
|
||||
} catch (Exception e) {
|
||||
log.error("获取存储统计数据失败", e);
|
||||
// 设置默认值
|
||||
storageStats.setTotalFiles(0);
|
||||
storageStats.setTotalImages(0);
|
||||
storageStats.setTodayUploads(0);
|
||||
storageStats.setTotalSize("0 B");
|
||||
storageStats.setStorageUsage(0.0);
|
||||
storageStats.setAvailableSpace("0 B");
|
||||
}
|
||||
|
||||
return storageStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取今日活跃统计数据
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Override
|
||||
public DashboardStatisticsVo.DailyActivityStatsVo getDailyActivityStats() {
|
||||
DashboardStatisticsVo.DailyActivityStatsVo activityStats =
|
||||
new DashboardStatisticsVo.DailyActivityStatsVo();
|
||||
|
||||
try {
|
||||
// 今日访问量
|
||||
LambdaQueryWrapper<SysOperLog> todayWrapper =
|
||||
new LambdaQueryWrapper<>();
|
||||
todayWrapper.apply("DATE(oper_time) = CURDATE()");
|
||||
Long todayVisits = sysOperLogMapper.selectCount(todayWrapper);
|
||||
activityStats.setTodayVisits(
|
||||
todayVisits != null ? todayVisits.intValue() : 0
|
||||
);
|
||||
|
||||
// 今日操作数(排除查询操作)
|
||||
LambdaQueryWrapper<SysOperLog> operWrapper =
|
||||
new LambdaQueryWrapper<>();
|
||||
operWrapper
|
||||
.apply("DATE(oper_time) = CURDATE()")
|
||||
// 排除查询操作
|
||||
.ne(SysOperLog::getOperType, "SELECT");
|
||||
Long todayOperations = sysOperLogMapper.selectCount(operWrapper);
|
||||
activityStats.setTodayOperations(
|
||||
todayOperations != null ? todayOperations.intValue() : 0
|
||||
);
|
||||
|
||||
// 活跃用户数(取用户统计中的活跃用户数)
|
||||
DashboardStatisticsVo.UserStatsVo userStats = getUserStats();
|
||||
activityStats.setActiveUsers(userStats.getActiveUsers());
|
||||
|
||||
// 新增内容数(今日新增的文件和图片)
|
||||
LambdaQueryWrapper<SysFile> fileWrapper =
|
||||
new LambdaQueryWrapper<>();
|
||||
fileWrapper.apply("DATE(create_time) = CURDATE()");
|
||||
Long newFiles = sysFileMapper.selectCount(fileWrapper);
|
||||
|
||||
LambdaQueryWrapper<SysPicture> pictureWrapper =
|
||||
new LambdaQueryWrapper<>();
|
||||
pictureWrapper.apply("DATE(create_time) = CURDATE()");
|
||||
Long newPictures = sysPictureMapper.selectCount(pictureWrapper);
|
||||
|
||||
int newContent =
|
||||
(newFiles != null ? newFiles.intValue() : 0) +
|
||||
(newPictures != null ? newPictures.intValue() : 0);
|
||||
activityStats.setNewContent(newContent);
|
||||
|
||||
// API调用次数(今日操作日志总数)
|
||||
activityStats.setApiCalls(activityStats.getTodayVisits());
|
||||
|
||||
// 平均响应时间(这里可以根据实际情况计算)
|
||||
// 示例数据
|
||||
activityStats.setAvgResponseTime(235);
|
||||
} catch (Exception e) {
|
||||
log.error("获取今日活跃统计数据失败", e);
|
||||
// 设置默认值
|
||||
activityStats.setTodayVisits(0);
|
||||
activityStats.setTodayOperations(0);
|
||||
activityStats.setActiveUsers(0);
|
||||
activityStats.setNewContent(0);
|
||||
activityStats.setApiCalls(0);
|
||||
activityStats.setAvgResponseTime(0);
|
||||
}
|
||||
|
||||
return activityStats;
|
||||
}
|
||||
}
|
||||
@ -36,14 +36,6 @@ public class ResultResponseHandler implements ResponseBodyAdvice<Object> {
|
||||
*/
|
||||
@Override
|
||||
public boolean supports(@Nullable MethodParameter methodParameter, @Nullable Class<? extends HttpMessageConverter<?>> CoderClass) {
|
||||
// 排除Swagger相关路径,避免干扰OpenAPI文档生成
|
||||
if (methodParameter != null && methodParameter.getMethod() != null) {
|
||||
String className = methodParameter.getMethod().getDeclaringClass().getName();
|
||||
// 排除SpringDoc相关的Controller
|
||||
if (className.contains("springdoc") || className.contains("swagger")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -52,15 +44,6 @@ public class ResultResponseHandler implements ResponseBodyAdvice<Object> {
|
||||
// 参数body 代表其实就是SpringMvc的请求的方法的结果
|
||||
// 对请求的结果在这里统一返回和处理
|
||||
|
||||
// 排除Swagger相关路径,避免包装OpenAPI文档
|
||||
String requestPath = serverHttpRequest.getURI().getPath();
|
||||
if (requestPath.startsWith("/v3/api-docs") ||
|
||||
requestPath.startsWith("/swagger-ui") ||
|
||||
requestPath.contains("/swagger") ||
|
||||
requestPath.contains("/api-docs")) {
|
||||
return body;
|
||||
}
|
||||
|
||||
if (body instanceof ErrorHandler errorHandler) {
|
||||
// 如果返回的结果是一个异常的结果,就把异常返回的结构数据倒腾到R.error里面即可
|
||||
return ResultUtils.error(errorHandler.getStatus(), errorHandler.getMsg());
|
||||
|
||||
@ -52,12 +52,6 @@ public class CoderSaTokenInterceptor implements WebMvcConfigurer {
|
||||
// ignoreUrls.add("/**/*.js");
|
||||
// 上传路径
|
||||
ignoreUrls.add(baseFilePath + "/**");
|
||||
// Swagger API文档相关路径
|
||||
ignoreUrls.add("/swagger-ui/**");
|
||||
ignoreUrls.add("/v3/api-docs/**");
|
||||
ignoreUrls.add("/v3/api-docs");
|
||||
ignoreUrls.add("/swagger-ui.html");
|
||||
ignoreUrls.add("/webjars/**");
|
||||
|
||||
// 除白名单路径外均需要登录认证
|
||||
SaRouter.match("/**").notMatch(ignoreUrls).check(r -> StpUtil.checkLogin());
|
||||
|
||||
Loading…
Reference in New Issue
Block a user