diff --git a/pom.xml b/pom.xml
index 411813c2..7e1c5939 100644
--- a/pom.xml
+++ b/pom.xml
@@ -183,7 +183,6 @@
${redisson.version}
-
org.springframework.boot
spring-boot-starter-websocket
diff --git a/src/main/java/com/youlai/system/config/WebSocketConfig.java b/src/main/java/com/youlai/system/config/WebSocketConfig.java
index a128f13f..bdadd200 100644
--- a/src/main/java/com/youlai/system/config/WebSocketConfig.java
+++ b/src/main/java/com/youlai/system/config/WebSocketConfig.java
@@ -20,13 +20,14 @@ import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
/**
- * WebSocket 配置
+ * WebSocket 自动配置类
*
* @author haoxr
* @since 2.4.0
*/
+// 启用WebSocket消息代理功能和配置STOMP协议,实现实时双向通信和消息传递
+@EnableWebSocketMessageBroker
@Configuration
-@EnableWebSocketMessageBroker // 启用WebSocket消息代理功能和配置STOMP协议,实现实时双向通信和消息传递
@Slf4j
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@@ -36,9 +37,12 @@ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
- .addEndpoint("/ws") // 注册了一个 /ws 的端点
- .setAllowedOriginPatterns("*") // 允许跨域的 WebSocket 连接
- .withSockJS(); // 启用 SockJS (浏览器不支持WebSocket,SockJS 将会提供兼容性支持)
+ // 注册 /ws 的端点
+ .addEndpoint("/ws")
+ // 允许跨域的 WebSocket 连接
+ .setAllowedOriginPatterns("*")
+ // 启用 SockJS (浏览器不支持WebSocket,SockJS 将会提供兼容性支持)
+ .withSockJS();
registry.addEndpoint("/ws-app").setAllowedOriginPatterns("*"); // 注册了一个 /ws-app 的端点,支持 uni-app 的 ws 连接协议
}
diff --git a/src/main/java/com/youlai/system/controller/StatsController.java b/src/main/java/com/youlai/system/controller/StatsController.java
new file mode 100644
index 00000000..a4bc3449
--- /dev/null
+++ b/src/main/java/com/youlai/system/controller/StatsController.java
@@ -0,0 +1,44 @@
+package com.youlai.system.controller;
+
+import com.youlai.system.common.result.Result;
+import com.youlai.system.model.vo.VisitTrendVO;
+import com.youlai.system.service.SysLogService;
+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 org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.time.LocalDate;
+
+
+/**
+ * 统计数据控制层
+ *
+ * @author Ray
+ * @since 2.10.0
+ */
+@Tag(name = "09.统计数据")
+@RestController
+@RequestMapping("/api/v1/stats")
+@RequiredArgsConstructor
+public class StatsController {
+
+ private final SysLogService logService;
+
+ @Operation(summary = "获取访问趋势")
+ @GetMapping("/visit-trend")
+ public Result getVisitTrend(
+ @Parameter(description = "开始时间", example = "yyyy-MM-dd") @RequestParam String startDate,
+ @Parameter(description = "结束时间", example = "yyyy-MM-dd") @RequestParam String endDate
+ ) {
+ LocalDate start = LocalDate.parse(startDate);
+ LocalDate end = LocalDate.parse(endDate);
+ VisitTrendVO data = logService.getVisitTrend(start, end);
+ return Result.success(data);
+ }
+
+}
diff --git a/src/main/java/com/youlai/system/controller/SysLogController.java b/src/main/java/com/youlai/system/controller/SysLogController.java
index 1c82582b..36812516 100644
--- a/src/main/java/com/youlai/system/controller/SysLogController.java
+++ b/src/main/java/com/youlai/system/controller/SysLogController.java
@@ -2,6 +2,7 @@ package com.youlai.system.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.system.common.result.PageResult;
+import com.youlai.system.model.query.LogPageQuery;
import com.youlai.system.model.query.RolePageQuery;
import com.youlai.system.model.vo.LogPageVO;
import com.youlai.system.service.SysLogService;
@@ -28,7 +29,7 @@ public class SysLogController {
@Operation(summary = "日志分页列表")
@GetMapping("/page")
public PageResult listPagedLogs(
- RolePageQuery queryParams
+ LogPageQuery queryParams
) {
Page result = logService.listPagedLogs(queryParams);
return PageResult.success(result);
diff --git a/src/main/java/com/youlai/system/mapper/SysLogMapper.java b/src/main/java/com/youlai/system/mapper/SysLogMapper.java
index 980b4c89..38a27432 100644
--- a/src/main/java/com/youlai/system/mapper/SysLogMapper.java
+++ b/src/main/java/com/youlai/system/mapper/SysLogMapper.java
@@ -1,12 +1,16 @@
package com.youlai.system.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.youlai.system.model.bo.VisitCount;
import com.youlai.system.model.entity.SysLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.youlai.system.model.query.LogPageQuery;
import com.youlai.system.model.query.RolePageQuery;
import com.youlai.system.model.vo.LogPageVO;
import org.apache.ibatis.annotations.Mapper;
+import java.util.List;
+
/**
* 系统日志 数据库访问层
@@ -17,7 +21,32 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SysLogMapper extends BaseMapper {
- Page listPagedLogs(Page page, RolePageQuery queryParams);
+ /**
+ * 获取日志分页列表
+ *
+ * @param page
+ * @param queryParams
+ * @return
+ */
+ Page listPagedLogs(Page page, LogPageQuery queryParams);
+
+ /**
+ * 统计浏览数(PV)
+ *
+ * @param startDate 开始日期 yyyy-MM-dd
+ * @param endDate 结束日期 yyyy-MM-dd
+ * @return
+ */
+ List getPvCounts(String startDate, String endDate);
+
+ /**
+ * 统计IP数
+ *
+ * @param startDate 开始日期 yyyy-MM-dd
+ * @param endDate 结束日期 yyyy-MM-dd
+ * @return
+ */
+ List getIpCounts(String startDate, String endDate);
}
diff --git a/src/main/java/com/youlai/system/model/bo/VisitCount.java b/src/main/java/com/youlai/system/model/bo/VisitCount.java
new file mode 100644
index 00000000..3c9a22c0
--- /dev/null
+++ b/src/main/java/com/youlai/system/model/bo/VisitCount.java
@@ -0,0 +1,23 @@
+package com.youlai.system.model.bo;
+
+import lombok.Data;
+
+/**
+ * 特定日期访问统计
+ *
+ * @author Ray
+ * @since 2.10.0
+ */
+@Data
+public class VisitCount {
+
+ /**
+ * 日期 yyyy-MM-dd
+ */
+ private String date;
+
+ /**
+ * 访问次数
+ */
+ private Integer count;
+}
diff --git a/src/main/java/com/youlai/system/model/query/LogPageQuery.java b/src/main/java/com/youlai/system/model/query/LogPageQuery.java
index 28760476..2d0d3942 100644
--- a/src/main/java/com/youlai/system/model/query/LogPageQuery.java
+++ b/src/main/java/com/youlai/system/model/query/LogPageQuery.java
@@ -4,6 +4,7 @@ import com.youlai.system.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
/**
* 日志分页查询对象
@@ -18,4 +19,13 @@ public class LogPageQuery extends BasePageQuery {
@Schema(description="关键字(日志内容/请求路径/请求方法/地区/浏览器/终端系统)")
private String keywords;
+
+ @Schema(description="开始日期")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private String startDate;
+
+ @Schema(description="结束日期")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private String endDate;
+
}
diff --git a/src/main/java/com/youlai/system/model/query/RolePageQuery.java b/src/main/java/com/youlai/system/model/query/RolePageQuery.java
index 102f8df4..02c0eb93 100644
--- a/src/main/java/com/youlai/system/model/query/RolePageQuery.java
+++ b/src/main/java/com/youlai/system/model/query/RolePageQuery.java
@@ -1,10 +1,13 @@
package com.youlai.system.model.query;
+import com.fasterxml.jackson.annotation.JsonFormat;
import com.youlai.system.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
+import java.time.LocalDateTime;
+
/**
* 角色分页查询对象
*
@@ -18,4 +21,12 @@ public class RolePageQuery extends BasePageQuery {
@Schema(description="关键字(角色名称/角色编码)")
private String keywords;
+
+ @Schema(description="开始日期")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ private LocalDateTime startDate;
+
+ @Schema(description="结束日期")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ private LocalDateTime endDate;
}
diff --git a/src/main/java/com/youlai/system/model/vo/VisitTrendVO.java b/src/main/java/com/youlai/system/model/vo/VisitTrendVO.java
new file mode 100644
index 00000000..2e686d58
--- /dev/null
+++ b/src/main/java/com/youlai/system/model/vo/VisitTrendVO.java
@@ -0,0 +1,27 @@
+package com.youlai.system.model.vo;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Schema(description = "访问趋势VO")
+@Getter
+@Setter
+public class VisitTrendVO {
+
+ @Schema(description = "日期列表")
+ private List dates;
+
+ @Schema(description = "浏览量(PV)")
+ private List pvList;
+
+ @Schema(description = "访客数(UV)")
+ private List uvList;
+
+ @Schema(description = "IP数")
+ private List ipList;
+
+}
diff --git a/src/main/java/com/youlai/system/service/SysLogService.java b/src/main/java/com/youlai/system/service/SysLogService.java
index a6b017c4..d1be9085 100644
--- a/src/main/java/com/youlai/system/service/SysLogService.java
+++ b/src/main/java/com/youlai/system/service/SysLogService.java
@@ -3,8 +3,12 @@ package com.youlai.system.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.system.model.entity.SysLog;
import com.baomidou.mybatisplus.extension.service.IService;
+import com.youlai.system.model.query.LogPageQuery;
import com.youlai.system.model.query.RolePageQuery;
import com.youlai.system.model.vo.LogPageVO;
+import com.youlai.system.model.vo.VisitTrendVO;
+
+import java.time.LocalDate;
/**
* 系统日志 服务接口
@@ -14,5 +18,21 @@ import com.youlai.system.model.vo.LogPageVO;
*/
public interface SysLogService extends IService {
- Page listPagedLogs(RolePageQuery queryParams);
+ /**
+ * 获取日志分页列表
+ *
+ * @param queryParams 查询参数
+ * @return
+ */
+ Page listPagedLogs(LogPageQuery queryParams);
+
+
+ /**
+ * 获取访问趋势
+ *
+ * @param startDate 开始时间
+ * @param endDate 结束时间
+ * @return
+ */
+ VisitTrendVO getVisitTrend(LocalDate startDate, LocalDate endDate);
}
diff --git a/src/main/java/com/youlai/system/service/impl/SysLogServiceImpl.java b/src/main/java/com/youlai/system/service/impl/SysLogServiceImpl.java
index 2045187b..1a69b828 100644
--- a/src/main/java/com/youlai/system/service/impl/SysLogServiceImpl.java
+++ b/src/main/java/com/youlai/system/service/impl/SysLogServiceImpl.java
@@ -2,13 +2,22 @@ package com.youlai.system.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.youlai.system.common.util.DateUtils;
+import com.youlai.system.model.bo.VisitCount;
import com.youlai.system.model.entity.SysLog;
-import com.youlai.system.model.query.RolePageQuery;
+import com.youlai.system.model.query.LogPageQuery;
import com.youlai.system.model.vo.LogPageVO;
+import com.youlai.system.model.vo.VisitTrendVO;
import com.youlai.system.service.SysLogService;
import com.youlai.system.mapper.SysLogMapper;
import org.springframework.stereotype.Service;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
/**
* 系统日志 服务实现类
*
@@ -26,10 +35,55 @@ public class SysLogServiceImpl extends ServiceImpl
* @return
*/
@Override
- public Page listPagedLogs(RolePageQuery queryParams) {
+ public Page listPagedLogs(LogPageQuery queryParams) {
+ // 格式化为数据库日期格式,避免日期比较使用格式化函数导致索引失效
+ DateUtils.toDatabaseFormat(queryParams, "startDate", "endDate");
+
return this.baseMapper.listPagedLogs(new Page(queryParams.getPageNum(), queryParams.getPageSize()),
queryParams);
}
+
+ /**
+ * 获取访问趋势
+ *
+ * @param startDate 开始时间
+ * @param endDate 结束时间
+ * @return
+ */
+ @Override
+ public VisitTrendVO getVisitTrend(LocalDate startDate, LocalDate endDate) {
+ VisitTrendVO visitTrend= new VisitTrendVO();
+ List dates = new ArrayList<>();
+
+ // 获取日期范围内的日期
+ while (!startDate.isAfter(endDate)) {
+ dates.add(startDate.toString());
+ startDate = startDate.plusDays(1);
+ }
+ visitTrend.setDates(dates);
+
+ // 获取访问量和访问 IP 数的统计数据
+ List pvCounts = this.baseMapper.getPvCounts(dates.get(0) + " 00:00:00", dates.get(dates.size() - 1) + " 23:59:59");
+ List ipCounts = this.baseMapper.getIpCounts(dates.get(0) + " 00:00:00", dates.get(dates.size() - 1) + " 23:59:59");
+
+ // 将统计数据转换为 Map
+ Map pvMap = pvCounts.stream().collect(Collectors.toMap(VisitCount::getDate, VisitCount::getCount));
+ Map ipMap = ipCounts.stream().collect(Collectors.toMap(VisitCount::getDate, VisitCount::getCount));
+
+ // 匹配日期和访问量/访问 IP 数
+ List pvList = new ArrayList<>();
+ List ipList = new ArrayList<>();
+
+ for (String date : dates) {
+ pvList.add(pvMap.getOrDefault(date, 0));
+ ipList.add(ipMap.getOrDefault(date, 0));
+ }
+
+ visitTrend.setPvList(pvList);
+ visitTrend.setIpList(ipList);
+
+ return visitTrend;
+ }
}
diff --git a/src/main/resources/mapper/SysLogMapper.xml b/src/main/resources/mapper/SysLogMapper.xml
index bbae642f..1056a8c1 100644
--- a/src/main/resources/mapper/SysLogMapper.xml
+++ b/src/main/resources/mapper/SysLogMapper.xml
@@ -33,8 +33,40 @@
t2.nickname LIKE concat('%',#{queryParams.keywords},'%')
)
+
+ AND t1.create_time >= #{queryParams.startDate}
+
+
+ AND t1.create_time <= #{queryParams.endDate}
+
ORDER BY
t1.create_time DESC
+
+
+
+
+
+