From 9e10a89c80da1e04794163822944ab29be0178a5 Mon Sep 17 00:00:00 2001 From: haotianmingyue <2421912570@qq.com> Date: Wed, 6 Nov 2024 15:31:01 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=9A=E8=BF=87socket=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E7=94=A8=E6=88=B7=E5=9C=A8=E7=BA=BF=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/SysUserOnlineTimeController.java | 40 ++++ .../WebSocketHeartbeatController.java | 41 ++++ .../src/main/resources/application.yml | 2 +- .../framework/config/SecurityConfig.java | 3 +- .../framework/web/service/TokenService.java | 21 ++ .../websocket/LocationWebSocketServer.java | 61 +++-- .../UserOnlineTimeWebSocketServer.java | 154 ++++++++++++ .../websocket/WebSocketComponentConfig.java | 20 +- .../framework/websocket/WebSocketConfig.java | 35 ++- .../framework/websocket/WebSocketServer.java | 212 ++++++++-------- .../framework/websocket/WebSocketUsers.java | 149 ++++-------- .../controller/DailyUserController.java | 104 ++++++++ .../system/controller/StUserController.java | 104 ++++++++ .../controller/SysMessageController.java | 104 ++++++++ .../SysMessageRecordController.java | 104 ++++++++ .../com/ruoyi/system/domain/DailyUser.java | 140 +++++++++++ .../ruoyi/system/domain/HeartbeatMessage.java | 22 ++ .../system/domain/HeartbeatResponse.java | 28 +++ .../java/com/ruoyi/system/domain/StUser.java | 169 +++++++++++++ .../com/ruoyi/system/domain/SysMessage.java | 124 ++++++++++ .../ruoyi/system/domain/SysMessageRecord.java | 99 ++++++++ .../system/domain/SysUserOnlineStats.java | 18 ++ .../system/domain/SysUserOnlineTime.java | 75 ++++++ .../ruoyi/system/mapper/DailyUserMapper.java | 70 ++++++ .../com/ruoyi/system/mapper/StUserMapper.java | 63 +++++ .../ruoyi/system/mapper/SysMessageMapper.java | 61 +++++ .../system/mapper/SysMessageRecordMapper.java | 61 +++++ .../system/service/IDailyUserService.java | 61 +++++ .../ruoyi/system/service/IStUserService.java | 61 +++++ .../service/ISysMessageRecordService.java | 61 +++++ .../system/service/ISysMessageService.java | 61 +++++ .../service/ISysUserOnlineTimeService.java | 19 ++ .../service/impl/DailyUserServiceImpl.java | 96 ++++++++ .../service/impl/StUserServiceImpl.java | 96 ++++++++ .../impl/SysMessageRecordServiceImpl.java | 96 ++++++++ .../service/impl/SysMessageServiceImpl.java | 96 ++++++++ .../impl/SysUserOnlineTimeServiceImpl.java | 226 ++++++++++++++++++ .../mapper/system/DailyUserMapper.xml | 106 ++++++++ .../resources/mapper/system/StUserMapper.xml | 108 +++++++++ .../mapper/system/SysMessageMapper.xml | 96 ++++++++ .../mapper/system/SysMessageRecordMapper.xml | 79 ++++++ .../mapper/system/UserInfoMapper.xml | 8 +- 42 files changed, 3109 insertions(+), 245 deletions(-) create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/SysUserOnlineTimeController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/websocket/WebSocketHeartbeatController.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/UserOnlineTimeWebSocketServer.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/controller/DailyUserController.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/controller/StUserController.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMessageController.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMessageRecordController.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/DailyUser.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/HeartbeatMessage.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/HeartbeatResponse.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/StUser.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessage.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessageRecord.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnlineStats.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnlineTime.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/DailyUserMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/StUserMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageRecordMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/IDailyUserService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/IStUserService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageRecordService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineTimeService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DailyUserServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StUserServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageRecordServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineTimeServiceImpl.java create mode 100644 ruoyi-system/src/main/resources/mapper/system/DailyUserMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/StUserMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysMessageMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysMessageRecordMapper.xml diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/SysUserOnlineTimeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/SysUserOnlineTimeController.java new file mode 100644 index 00000000..f5c90fe0 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/SysUserOnlineTimeController.java @@ -0,0 +1,40 @@ +package com.ruoyi.web.controller.app; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.system.service.ISysUserOnlineTimeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import static com.ruoyi.common.utils.SecurityUtils.getUserId; + + +//备用的,当websocket不能用时,应急的. +@RestController +@RequestMapping("/app/user/online") +public class SysUserOnlineTimeController { + + @Autowired + private ISysUserOnlineTimeService userOnlineTimeService; + + // 暂时用不到 +// @GetMapping("/stats/{userId}") +// public AjaxResult getUserOnlineStats(@PathVariable Long userId) { +// return AjaxResult.success(userOnlineTimeService.selectUserOnlineStats(userId)); +// } + // 这就纯纯为了socket失败备用的请求地址 + @PostMapping("/heartbeat") + public AjaxResult heartbeat() { + Long userId = getUserId(); + userOnlineTimeService.updateUserHeartbeat(userId); + return AjaxResult.success(); + } + + @PostMapping("/logout") + public AjaxResult logout() { + Long userId = getUserId(); + userOnlineTimeService.recordUserLogout(userId); + return AjaxResult.success(); + } + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/websocket/WebSocketHeartbeatController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/websocket/WebSocketHeartbeatController.java new file mode 100644 index 00000000..b74b06a7 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/websocket/WebSocketHeartbeatController.java @@ -0,0 +1,41 @@ +//package com.ruoyi.web.controller.app.websocket; +// +//import com.ruoyi.system.domain.HeartbeatMessage; +//import com.ruoyi.system.domain.HeartbeatResponse; +//import com.ruoyi.system.service.ISysUserOnlineTimeService; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.messaging.handler.annotation.MessageMapping; +//import org.springframework.messaging.handler.annotation.Payload; +//import org.springframework.messaging.simp.annotation.SendToUser; +//import org.springframework.stereotype.Controller; +// +//@Controller +//public class WebSocketHeartbeatController { +// +// @Autowired +// private ISysUserOnlineTimeService userOnlineTimeService; +// +// @MessageMapping("/heartbeat") +// @SendToUser("/queue/heartbeat") +// public HeartbeatResponse handleHeartbeat(@Payload HeartbeatMessage message) { +// try { +// if (message == null || message.getUserId() == null) { +// +// System.out.println("接收到无效的心跳消息"); +//// log.error("接收到无效的心跳消息"); +// return new HeartbeatResponse(System.currentTimeMillis(), "无效的心跳消息"); +// } +// +// // 更新用户在线时长 +// userOnlineTimeService.updateUserHeartbeat(message.getUserId()); +// // 返回心跳响应 +// return new HeartbeatResponse(message.getTimestamp(), "success"); +// } catch (Exception e) { +// System.out.println("处理心跳消息时发生错误"); +//// log.error("处理心跳消息时发生错误", e); +// return new HeartbeatResponse(System.currentTimeMillis(), "error"); +// } +// } +//} +// +// diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 3c626bbe..cdce62cb 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -97,7 +97,7 @@ token: # 令牌密钥 secret: abcdefghijklmnopqrstuvwxyz # 令牌有效期(默认30分钟)1440 = 60*24 - expireTime: 1440 + expireTime: 43200 # MyBatis配置 mybatis: diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java index 1b42210f..359ef897 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -122,7 +122,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter .antMatchers("/login", "/register", "/captchaImage","/appLoginCaptchaCode/**","/appCaptchaCode/**","/appUpdatePasswordCaptchaCode/**" ,"/app/system/loginPassword","/app/system/register", "/app/system/loginSms" ,"/registerCheckPhone","/app/system/forgetPassword" - ,"/websocket/location" +// ,"/websocket/location/**" +// ,"/websocket/online/**" // , "/verifyRegisterSms" // ,"/app/system/**" diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java index 4b190d02..c925addd 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java @@ -76,6 +76,27 @@ public class TokenService } return null; } + /** + * 根据token获取用户Id + */ + public Long getUserIdByToken(String token){ + if (StringUtils.isNotEmpty(token)) + { + try + { + Claims claims = parseToken(token); + // 解析对应的权限以及用户信息 + String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); + String userKey = getTokenKey(uuid); + LoginUser user = redisCache.getCacheObject(userKey); + return user.getUserId(); + } + catch (Exception e) + { + } + } + return null; + } /** * 设置用户身份信息 diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/LocationWebSocketServer.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/LocationWebSocketServer.java index 37b17ccd..0d3fb5e0 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/LocationWebSocketServer.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/LocationWebSocketServer.java @@ -8,19 +8,20 @@ import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.websocket.*; +import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.util.List; import java.util.concurrent.Semaphore; @Component -@ServerEndpoint("/websocket/location") +@ServerEndpoint("/websocket/location/{userId}") public class LocationWebSocketServer { private static final Logger LOGGER = LoggerFactory.getLogger(LocationWebSocketServer.class); private static final int MAX_ONLINE_COUNT = 1000; private static final Semaphore SEMAPHORE = new Semaphore(MAX_ONLINE_COUNT); - private static LocationService locationService; - private static ObjectMapper objectMapper; + private static volatile LocationService locationService; + private static volatile ObjectMapper objectMapper; public static void setLocationService(LocationService service) { LocationWebSocketServer.locationService = service; @@ -31,39 +32,61 @@ public class LocationWebSocketServer { } @OnOpen - public void onOpen(Session session) { - if (!SemaphoreUtils.tryAcquire(SEMAPHORE)) { - WebSocketUsers.sendMessageToUserByText(session, "当前在线人数超过限制:" + MAX_ONLINE_COUNT); - try { + public void onOpen(@PathParam("userId") String userId, Session session) { + try { + if (!SemaphoreUtils.tryAcquire(SEMAPHORE)) { + WebSocketUsers.sendMessageToUserByText(session, "当前在线人数超过限制:" + MAX_ONLINE_COUNT); session.close(); - } catch (Exception e) { - LOGGER.error("关闭连接异常", e); + return; } - return; + + // 保存用户连接 + WebSocketUsers.put(userId, session); + LOGGER.info("用户[{}]建立连接", userId); + + // 发送当前在线人数 + String message = String.format("连接成功,当前在线人数:%d", WebSocketUsers.getOnlineCount()); + WebSocketUsers.sendMessageToUserByText(session, message); + } catch (Exception e) { + LOGGER.error("连接建立失败", e); + SemaphoreUtils.release(SEMAPHORE); + } + } + + private void checkDependencies() { + if (locationService == null || objectMapper == null) { + throw new IllegalStateException("必要的依赖未注入,请检查LocationService和ObjectMapper是否已经设置"); } - WebSocketUsers.put(session.getId(), session); - LOGGER.info("建立连接 - {}", session.getId()); } @OnMessage public void onMessage(String message, Session session) { try { -// System.out.println(message); + checkDependencies(); + + String userId = WebSocketUsers.getUserId(session); + if (userId == null) { + WebSocketUsers.sendMessageToUserByText(session, "未找到用户信息,请重新连接"); + return; + } + + LOGGER.info("收到用户[{}]的消息: {}", userId, message); UserLocation location = objectMapper.readValue(message, UserLocation.class); - System.out.println(location.getUserId()); + // 验证用户ID是否匹配 + if (!userId.equals(location.getUserId())) { + WebSocketUsers.sendMessageToUserByText(session, "用户ID不匹配"); + return; + } - // 这里直接从前端传递id.不安全 locationService.updateLocation(location); - - //获取附近5公里用户的位置 List nearbyUsers = locationService.getNearbyUsers(location.getUserId(), 5.0); String responseMessage = objectMapper.writeValueAsString(nearbyUsers); - // 广播位置信息给所有用户 - WebSocketUsers.broadcastLocation(responseMessage); + WebSocketUsers.sendMessageToUserByText(session, responseMessage); } catch (Exception e) { LOGGER.error("处理消息失败", e); + WebSocketUsers.sendMessageToUserByText(session, "消息处理失败: " + e.getMessage()); } } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/UserOnlineTimeWebSocketServer.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/UserOnlineTimeWebSocketServer.java new file mode 100644 index 00000000..10569a6d --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/UserOnlineTimeWebSocketServer.java @@ -0,0 +1,154 @@ +package com.ruoyi.framework.websocket; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.system.domain.HeartbeatMessage; +import com.ruoyi.system.domain.HeartbeatResponse; +import com.ruoyi.system.domain.UserLocation; +import com.ruoyi.system.service.ISysUserOnlineTimeService; +import com.ruoyi.system.service.impl.SysUserOnlineTimeServiceImpl; +import org.apache.ibatis.annotations.Param; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.handler.annotation.Payload; +import org.springframework.stereotype.Component; + +import javax.websocket.*; +import javax.websocket.server.PathParam; +import javax.websocket.server.ServerEndpoint; +import java.util.List; +import java.util.concurrent.Semaphore; +import com.ruoyi.system.domain.HeartbeatMessage; + + +@Component +// 把当前类标识成一个WebSocket的服务端 +@ServerEndpoint("/websocket/online/{token}") +public class UserOnlineTimeWebSocketServer { + private static final Logger LOGGER = LoggerFactory.getLogger(UserOnlineTimeWebSocketServer.class); + private static final int MAX_ONLINE_COUNT = 100000; + private static final Semaphore SEMAPHORE = new Semaphore(MAX_ONLINE_COUNT); + +// private static volatile LocationService locationService; + private static volatile ObjectMapper objectMapper; + + private static volatile SysUserOnlineTimeServiceImpl userOnlineTimeService; + + private static volatile TokenService tokenService; + + public static void setUserOnlineTimeService(SysUserOnlineTimeServiceImpl service) { + UserOnlineTimeWebSocketServer.userOnlineTimeService = service; + } + public static void setTokenService(TokenService service) { + UserOnlineTimeWebSocketServer.tokenService = service; + } + + public static void setObjectMapper(ObjectMapper mapper) { + UserOnlineTimeWebSocketServer.objectMapper = mapper; + } + + //socket 打开时的处理 + @OnOpen + public void onOpen(@PathParam("token") String token, Session session) { + try { + if (!SemaphoreUtils.tryAcquire(SEMAPHORE)) { + WebSocketUsers.sendMessageToUserByText(session, "当前在线人数超过限制:" + MAX_ONLINE_COUNT); + session.close(); + return; + } + + Long userId = tokenService.getUserIdByToken(token); + + // 保存用户连接 + WebSocketUsers.put(userId.toString(), session); + LOGGER.info("用户[{}]建立连接", userId); + + System.out.println("用户"+userId+"登录"); + + // 注册用户每天登录信息 + userOnlineTimeService.recordUserLogin(userId); + // 发送当前在线人数 +// String message = String.format("连接成功,当前在线人数:%d", WebSocketUsers.getOnlineCount()); + WebSocketUsers.sendMessageToUserByText(session, "连接成功"); + System.out.println(String.format("连接成功,当前在线人数:%d", WebSocketUsers.getOnlineCount())); + } catch (Exception e) { + LOGGER.error("连接建立失败", e); + SemaphoreUtils.release(SEMAPHORE); + } + } + +// private void checkDependencies() { +// if (locationService == null || objectMapper == null) { +// throw new IllegalStateException("必要的依赖未注入,请检查LocationService和ObjectMapper是否已经设置"); +// } +// } + + // 处理用户发送的消息 + @OnMessage + public void onMessage(String message, Session session) { + try { + + String userId = WebSocketUsers.getUserId(session); + if (userId == null) { + WebSocketUsers.sendMessageToUserByText(session, "未找到用户信息,请重新连接"); + return; + } + + LOGGER.info("收到用户[{}]的消息: {}", userId, message); + + HeartbeatMessage heartbeatMessage = objectMapper.readValue(message, HeartbeatMessage.class); + + Long userIdLong = Long.parseLong(userId); + Long timestamp = heartbeatMessage.getTimestamp(); + + if (userIdLong == null || timestamp == null) { + + System.out.println("接收到无效的心跳消息"); + LOGGER.error("接收到无效的心跳消息"); + WebSocketUsers.sendMessageToUserByText(session, "接收到无效的心跳消息"); + } + else{ + LOGGER.info("用户[{}]发送了心跳消息,时间戳为:{}", userIdLong, timestamp); + //更新用户在线时间 + int back = userOnlineTimeService.updateUserHeartbeat(userIdLong); + if(back>0){ + WebSocketUsers.sendMessageToUserByText(session, "更新在线时长成功"); + } + else{ + WebSocketUsers.sendMessageToUserByText(session, "更新在线时长失败"); + } + + } + + + } catch (Exception e) { + LOGGER.error("处理消息失败", e); + WebSocketUsers.sendMessageToUserByText(session, "消息处理失败: " + e.getMessage()); + } + } + + @OnClose + public void onClose(Session session) { + + String userId = WebSocketUsers.getUserId(session); + Long userIdLong = Long.parseLong(userId); + + if(userIdLong != null){ + userOnlineTimeService.recordUserLogout(userIdLong); + } + + WebSocketUsers.remove(session); + SemaphoreUtils.release(SEMAPHORE); + LOGGER.info("关闭连接 - {}", session.getId()); + } + + @OnError + public void onError(Session session, Throwable error) { + LOGGER.error("WebSocket错误", error); + WebSocketUsers.remove(session); + SemaphoreUtils.release(SEMAPHORE); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketComponentConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketComponentConfig.java index 84a0aceb..c83bf392 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketComponentConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketComponentConfig.java @@ -1,5 +1,7 @@ package com.ruoyi.framework.websocket; import com.fasterxml.jackson.databind.ObjectMapper; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.system.service.impl.SysUserOnlineTimeServiceImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Configuration; @@ -13,10 +15,21 @@ public class WebSocketComponentConfig { private final LocationService locationService; private final ObjectMapper objectMapper; + + private final SysUserOnlineTimeServiceImpl userOnlineTimeWebSocketServer; + private final TokenService tokenService; + private final ObjectMapper onlineTimeObjectMapper; + + // 使用构造器注入 - public WebSocketComponentConfig(LocationService locationService, ObjectMapper objectMapper) { + public WebSocketComponentConfig(LocationService locationService,SysUserOnlineTimeServiceImpl userOnlineTimeWebSocketServer, ObjectMapper objectMapper, ObjectMapper onlineTimeObjectMapper + , TokenService tokenService) { this.locationService = locationService; + this.userOnlineTimeWebSocketServer = userOnlineTimeWebSocketServer; + this.objectMapper = objectMapper; + this.onlineTimeObjectMapper = onlineTimeObjectMapper; + this.tokenService = tokenService; } @PostConstruct @@ -24,6 +37,11 @@ public class WebSocketComponentConfig { try { LocationWebSocketServer.setLocationService(locationService); LocationWebSocketServer.setObjectMapper(objectMapper); + + UserOnlineTimeWebSocketServer.setObjectMapper(onlineTimeObjectMapper); + UserOnlineTimeWebSocketServer.setTokenService(tokenService); + UserOnlineTimeWebSocketServer.setUserOnlineTimeService(userOnlineTimeWebSocketServer); + LOGGER.info("WebSocket组件初始化成功"); } catch (Exception e) { LOGGER.error("WebSocket组件初始化失败", e); diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketConfig.java index be63f35f..13590eef 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketConfig.java @@ -2,6 +2,10 @@ package com.ruoyi.framework.websocket; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; +import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** @@ -10,11 +14,34 @@ import org.springframework.web.socket.server.standard.ServerEndpointExporter; * @author ruoyi */ @Configuration -public class WebSocketConfig -{ +//@EnableWebSocketMessageBroker +public class WebSocketConfig { + /** + * ServerEndpointExporter 作用 + * 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint + * 前提是直接使用springboot的内置容器 + */ @Bean - public ServerEndpointExporter serverEndpointExporter() - { + public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } + +// @Override +// public void registerStompEndpoints(StompEndpointRegistry registry) { +// registry.addEndpoint("/ws") +// .setAllowedOrigins("*") +// .withSockJS(); +// } +// +// @Override +// public void configureMessageBroker(MessageBrokerRegistry config) { +// // 设置消息代理的前缀 +// config.enableSimpleBroker("/topic", "/queue"); +// +// // 设置应用的前缀 +// config.setApplicationDestinationPrefixes("/app"); +// +// // 设置用户目的地前缀 +// config.setUserDestinationPrefix("/user"); +// } } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketServer.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketServer.java index 4ce319c4..2a9db845 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketServer.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketServer.java @@ -1,106 +1,106 @@ -package com.ruoyi.framework.websocket; - -import java.util.concurrent.Semaphore; -import javax.websocket.OnClose; -import javax.websocket.OnError; -import javax.websocket.OnMessage; -import javax.websocket.OnOpen; -import javax.websocket.Session; -import javax.websocket.server.ServerEndpoint; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -/** - * websocket 消息处理 - * - * @author ruoyi - */ -@Component -@ServerEndpoint("/websocket/message") -public class WebSocketServer -{ - /** - * WebSocketServer 日志控制器 - */ - private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class); - - /** - * 默认最多允许同时在线人数100 - */ - public static int socketMaxOnlineCount = 100; - - private static Semaphore socketSemaphore = new Semaphore(socketMaxOnlineCount); - - /** - * 连接建立成功调用的方法 - */ - @OnOpen - public void onOpen(Session session) throws Exception - { - boolean semaphoreFlag = false; - // 尝试获取信号量 - semaphoreFlag = SemaphoreUtils.tryAcquire(socketSemaphore); - if (!semaphoreFlag) - { - // 未获取到信号量 - LOGGER.error("\n 当前在线人数超过限制数- {}", socketMaxOnlineCount); - WebSocketUsers.sendMessageToUserByText(session, "当前在线人数超过限制数:" + socketMaxOnlineCount); - session.close(); - } - else - { - // 添加用户 - WebSocketUsers.put(session.getId(), session); - LOGGER.info("\n 建立连接 - {}", session); - LOGGER.info("\n 当前人数 - {}", WebSocketUsers.getUsers().size()); - WebSocketUsers.sendMessageToUserByText(session, "连接成功"); - } - } - - /** - * 连接关闭时处理 - */ - @OnClose - public void onClose(Session session) - { - LOGGER.info("\n 关闭连接 - {}", session); - // 移除用户 - boolean removeFlag = WebSocketUsers.remove(session.getId()); - if (!removeFlag) - { - // 获取到信号量则需释放 - SemaphoreUtils.release(socketSemaphore); - } - } - - /** - * 抛出异常时处理 - */ - @OnError - public void onError(Session session, Throwable exception) throws Exception - { - if (session.isOpen()) - { - // 关闭连接 - session.close(); - } - String sessionId = session.getId(); - LOGGER.info("\n 连接异常 - {}", sessionId); - LOGGER.info("\n 异常信息 - {}", exception); - // 移出用户 - WebSocketUsers.remove(sessionId); - // 获取到信号量则需释放 - SemaphoreUtils.release(socketSemaphore); - } - - /** - * 服务器接收到客户端消息时调用的方法 - */ - @OnMessage - public void onMessage(String message, Session session) - { - String msg = message.replace("你", "我").replace("吗", ""); - WebSocketUsers.sendMessageToUserByText(session, msg); - } -} +//package com.ruoyi.framework.websocket; +// +//import java.util.concurrent.Semaphore; +//import javax.websocket.OnClose; +//import javax.websocket.OnError; +//import javax.websocket.OnMessage; +//import javax.websocket.OnOpen; +//import javax.websocket.Session; +//import javax.websocket.server.ServerEndpoint; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +//import org.springframework.stereotype.Component; +// +///** +// * websocket 消息处理 +// * +// * @author ruoyi +// */ +//@Component +//@ServerEndpoint("/websocket/message") +//public class WebSocketServer +//{ +// /** +// * WebSocketServer 日志控制器 +// */ +// private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class); +// +// /** +// * 默认最多允许同时在线人数100 +// */ +// public static int socketMaxOnlineCount = 100; +// +// private static Semaphore socketSemaphore = new Semaphore(socketMaxOnlineCount); +// +// /** +// * 连接建立成功调用的方法 +// */ +// @OnOpen +// public void onOpen(Session session) throws Exception +// { +// boolean semaphoreFlag = false; +// // 尝试获取信号量 +// semaphoreFlag = SemaphoreUtils.tryAcquire(socketSemaphore); +// if (!semaphoreFlag) +// { +// // 未获取到信号量 +// LOGGER.error("\n 当前在线人数超过限制数- {}", socketMaxOnlineCount); +// WebSocketUsers.sendMessageToUserByText(session, "当前在线人数超过限制数:" + socketMaxOnlineCount); +// session.close(); +// } +// else +// { +// // 添加用户 +// WebSocketUsers.put(session.getId(), session); +// LOGGER.info("\n 建立连接 - {}", session); +// LOGGER.info("\n 当前人数 - {}", WebSocketUsers.getUsers().size()); +// WebSocketUsers.sendMessageToUserByText(session, "连接成功"); +// } +// } +// +// /** +// * 连接关闭时处理 +// */ +// @OnClose +// public void onClose(Session session) +// { +// LOGGER.info("\n 关闭连接 - {}", session); +// // 移除用户 +// boolean removeFlag = WebSocketUsers.remove(session.getId()); +// if (!removeFlag) +// { +// // 获取到信号量则需释放 +// SemaphoreUtils.release(socketSemaphore); +// } +// } +// +// /** +// * 抛出异常时处理 +// */ +// @OnError +// public void onError(Session session, Throwable exception) throws Exception +// { +// if (session.isOpen()) +// { +// // 关闭连接 +// session.close(); +// } +// String sessionId = session.getId(); +// LOGGER.info("\n 连接异常 - {}", sessionId); +// LOGGER.info("\n 异常信息 - {}", exception); +// // 移出用户 +// WebSocketUsers.remove(sessionId); +// // 获取到信号量则需释放 +// SemaphoreUtils.release(socketSemaphore); +// } +// +// /** +// * 服务器接收到客户端消息时调用的方法 +// */ +// @OnMessage +// public void onMessage(String message, Session session) +// { +// String msg = message.replace("你", "我").replace("吗", ""); +// WebSocketUsers.sendMessageToUserByText(session, msg); +// } +//} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketUsers.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketUsers.java index df47680a..2fdee706 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketUsers.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/websocket/WebSocketUsers.java @@ -14,132 +14,63 @@ import org.slf4j.LoggerFactory; * * @author ruoyi */ -public class WebSocketUsers -{ - /** - * WebSocketUsers 日志控制器 - */ +public class WebSocketUsers { private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketUsers.class); - /** - * 用户集 - */ - private static Map USERS = new ConcurrentHashMap<>(); + // 保存用户ID和Session的映射 + private static final Map USER_SESSIONS = new ConcurrentHashMap<>(); + // 保存Session和用户ID的映射 + private static final Map SESSION_USERS = new ConcurrentHashMap<>(); - /** - * 存储用户 - * - * @param key 唯一键 - * @param session 用户信息 - */ - public static void put(String key, Session session) - { - USERS.put(key, session); - } - - /** - * 移除用户 - * - * @param session 用户信息 - * - * @return 移除结果 - */ - public static boolean remove(Session session) - { - String key = null; - boolean flag = USERS.containsValue(session); - if (flag) - { - Set> entries = USERS.entrySet(); - for (Map.Entry entry : entries) - { - Session value = entry.getValue(); - if (value.equals(session)) - { - key = entry.getKey(); - break; - } + public static void put(String userId, Session session) { + // 如果该用户已经有连接,先关闭旧连接 + Session oldSession = USER_SESSIONS.get(userId); + if (oldSession != null && oldSession.isOpen()) { + try { + sendMessageToUserByText(oldSession, "您的账号在其他地方登录,当前连接将被关闭"); + oldSession.close(); + } catch (IOException e) { + LOGGER.error("关闭旧连接失败", e); } } - else - { - return true; - } - return remove(key); + + // 保存新连接 + USER_SESSIONS.put(userId, session); + SESSION_USERS.put(session.getId(), userId); + LOGGER.info("用户[{}]建立新连接", userId); } - /** - * 移出用户 - * - * @param key 键 - */ - public static boolean remove(String key) - { - LOGGER.info("\n 正在移出用户 - {}", key); - Session remove = USERS.remove(key); - if (remove != null) - { - boolean containsValue = USERS.containsValue(remove); - LOGGER.info("\n 移出结果 - {}", containsValue ? "失败" : "成功"); - return containsValue; - } - else - { - return true; + public static void remove(Session session) { + String userId = SESSION_USERS.remove(session.getId()); + if (userId != null) { + USER_SESSIONS.remove(userId); + LOGGER.info("用户[{}]断开连接", userId); } } - /** - * 获取在线用户列表 - * - * @return 返回用户集合 - */ - public static Map getUsers() - { - return USERS; + public static Session getSession(String userId) { + return USER_SESSIONS.get(userId); } - /** - * 群发消息文本消息 - * - * @param message 消息内容 - */ - public static void sendMessageToUsersByText(String message) - { - Collection values = USERS.values(); - for (Session value : values) - { - sendMessageToUserByText(value, message); + public static String getUserId(Session session) { + return SESSION_USERS.get(session.getId()); + } + + public static void sendMessageToUserByText(Session session, String message) { + try { + session.getBasicRemote().sendText(message); + } catch (IOException e) { + LOGGER.error("发送消息失败", e); } } - /** - * 发送文本消息 - * - * @param userName 自己的用户名 - * @param message 消息内容 - */ - public static void sendMessageToUserByText(Session session, String message) - { - if (session != null) - { - try - { - session.getBasicRemote().sendText(message); - } - catch (IOException e) - { - LOGGER.error("\n[发送消息异常]", e); - } - } - else - { - LOGGER.info("\n[你已离线]"); - } - } public static void broadcastLocation(String message) { - USERS.values().forEach(session -> { + USER_SESSIONS.values().forEach(session -> { sendMessageToUserByText(session, message); }); } + + public static int getOnlineCount() { + return USER_SESSIONS.size(); + } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/DailyUserController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/DailyUserController.java new file mode 100644 index 00000000..d8d9b3e0 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/DailyUserController.java @@ -0,0 +1,104 @@ +package com.ruoyi.system.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.system.domain.DailyUser; +import com.ruoyi.system.service.IDailyUserService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * userDailyController + * + * @author 昊天 + * @date 2024-11-04 + */ +@RestController +@RequestMapping("/system/userDaily") +public class DailyUserController extends BaseController +{ + @Autowired + private IDailyUserService dailyUserService; + + /** + * 查询userDaily列表 + */ + @PreAuthorize("@ss.hasPermi('system:userDaily:list')") + @GetMapping("/list") + public TableDataInfo list(DailyUser dailyUser) + { + startPage(); + List list = dailyUserService.selectDailyUserList(dailyUser); + return getDataTable(list); + } + + /** + * 导出userDaily列表 + */ + @PreAuthorize("@ss.hasPermi('system:userDaily:export')") + @Log(title = "userDaily", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, DailyUser dailyUser) + { + List list = dailyUserService.selectDailyUserList(dailyUser); + ExcelUtil util = new ExcelUtil(DailyUser.class); + util.exportExcel(response, list, "userDaily数据"); + } + + /** + * 获取userDaily详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:userDaily:query')") + @GetMapping(value = "/{dailyUserId}") + public AjaxResult getInfo(@PathVariable("dailyUserId") Long dailyUserId) + { + return success(dailyUserService.selectDailyUserByDailyUserId(dailyUserId)); + } + + /** + * 新增userDaily + */ + @PreAuthorize("@ss.hasPermi('system:userDaily:add')") + @Log(title = "userDaily", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody DailyUser dailyUser) + { + return toAjax(dailyUserService.insertDailyUser(dailyUser)); + } + + /** + * 修改userDaily + */ + @PreAuthorize("@ss.hasPermi('system:userDaily:edit')") + @Log(title = "userDaily", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody DailyUser dailyUser) + { + return toAjax(dailyUserService.updateDailyUser(dailyUser)); + } + + /** + * 删除userDaily + */ + @PreAuthorize("@ss.hasPermi('system:userDaily:remove')") + @Log(title = "userDaily", businessType = BusinessType.DELETE) + @DeleteMapping("/{dailyUserIds}") + public AjaxResult remove(@PathVariable Long[] dailyUserIds) + { + return toAjax(dailyUserService.deleteDailyUserByDailyUserIds(dailyUserIds)); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/StUserController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/StUserController.java new file mode 100644 index 00000000..754de78a --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/StUserController.java @@ -0,0 +1,104 @@ +package com.ruoyi.system.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.system.domain.StUser; +import com.ruoyi.system.service.IStUserService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 用户7/30天统计数据Controller + * + * @author haotian + * @date 2024-11-04 + */ +@RestController +@RequestMapping("/system/userSt") +public class StUserController extends BaseController +{ + @Autowired + private IStUserService stUserService; + + /** + * 查询用户7/30天统计数据列表 + */ + @PreAuthorize("@ss.hasPermi('system:userSt:list')") + @GetMapping("/list") + public TableDataInfo list(StUser stUser) + { + startPage(); + List list = stUserService.selectStUserList(stUser); + return getDataTable(list); + } + + /** + * 导出用户7/30天统计数据列表 + */ + @PreAuthorize("@ss.hasPermi('system:userSt:export')") + @Log(title = "用户7/30天统计数据", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, StUser stUser) + { + List list = stUserService.selectStUserList(stUser); + ExcelUtil util = new ExcelUtil(StUser.class); + util.exportExcel(response, list, "用户7/30天统计数据数据"); + } + + /** + * 获取用户7/30天统计数据详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:userSt:query')") + @GetMapping(value = "/{userId}") + public AjaxResult getInfo(@PathVariable("userId") Long userId) + { + return success(stUserService.selectStUserByUserId(userId)); + } + + /** + * 新增用户7/30天统计数据 + */ + @PreAuthorize("@ss.hasPermi('system:userSt:add')") + @Log(title = "用户7/30天统计数据", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody StUser stUser) + { + return toAjax(stUserService.insertStUser(stUser)); + } + + /** + * 修改用户7/30天统计数据 + */ + @PreAuthorize("@ss.hasPermi('system:userSt:edit')") + @Log(title = "用户7/30天统计数据", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody StUser stUser) + { + return toAjax(stUserService.updateStUser(stUser)); + } + + /** + * 删除用户7/30天统计数据 + */ + @PreAuthorize("@ss.hasPermi('system:userSt:remove')") + @Log(title = "用户7/30天统计数据", businessType = BusinessType.DELETE) + @DeleteMapping("/{userIds}") + public AjaxResult remove(@PathVariable Long[] userIds) + { + return toAjax(stUserService.deleteStUserByUserIds(userIds)); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMessageController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMessageController.java new file mode 100644 index 00000000..fc209c7c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMessageController.java @@ -0,0 +1,104 @@ +package com.ruoyi.system.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.system.domain.SysMessage; +import com.ruoyi.system.service.ISysMessageService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 系统消息Controller + * + * @author haotian + * @date 2024-11-04 + */ +@RestController +@RequestMapping("/system/sysMessage") +public class SysMessageController extends BaseController +{ + @Autowired + private ISysMessageService sysMessageService; + + /** + * 查询系统消息列表 + */ + @PreAuthorize("@ss.hasPermi('system:sysMessage:list')") + @GetMapping("/list") + public TableDataInfo list(SysMessage sysMessage) + { + startPage(); + List list = sysMessageService.selectSysMessageList(sysMessage); + return getDataTable(list); + } + + /** + * 导出系统消息列表 + */ + @PreAuthorize("@ss.hasPermi('system:sysMessage:export')") + @Log(title = "系统消息", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, SysMessage sysMessage) + { + List list = sysMessageService.selectSysMessageList(sysMessage); + ExcelUtil util = new ExcelUtil(SysMessage.class); + util.exportExcel(response, list, "系统消息数据"); + } + + /** + * 获取系统消息详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:sysMessage:query')") + @GetMapping(value = "/{messageId}") + public AjaxResult getInfo(@PathVariable("messageId") Long messageId) + { + return success(sysMessageService.selectSysMessageByMessageId(messageId)); + } + + /** + * 新增系统消息 + */ + @PreAuthorize("@ss.hasPermi('system:sysMessage:add')") + @Log(title = "系统消息", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SysMessage sysMessage) + { + return toAjax(sysMessageService.insertSysMessage(sysMessage)); + } + + /** + * 修改系统消息 + */ + @PreAuthorize("@ss.hasPermi('system:sysMessage:edit')") + @Log(title = "系统消息", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SysMessage sysMessage) + { + return toAjax(sysMessageService.updateSysMessage(sysMessage)); + } + + /** + * 删除系统消息 + */ + @PreAuthorize("@ss.hasPermi('system:sysMessage:remove')") + @Log(title = "系统消息", businessType = BusinessType.DELETE) + @DeleteMapping("/{messageIds}") + public AjaxResult remove(@PathVariable Long[] messageIds) + { + return toAjax(sysMessageService.deleteSysMessageByMessageIds(messageIds)); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMessageRecordController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMessageRecordController.java new file mode 100644 index 00000000..f26ea1fe --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMessageRecordController.java @@ -0,0 +1,104 @@ +package com.ruoyi.system.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.system.domain.SysMessageRecord; +import com.ruoyi.system.service.ISysMessageRecordService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 消息接收记录Controller + * + * @author haotian + * @date 2024-11-04 + */ +@RestController +@RequestMapping("/system/sysMessageRecord") +public class SysMessageRecordController extends BaseController +{ + @Autowired + private ISysMessageRecordService sysMessageRecordService; + + /** + * 查询消息接收记录列表 + */ + @PreAuthorize("@ss.hasPermi('system:sysMessageRecord:list')") + @GetMapping("/list") + public TableDataInfo list(SysMessageRecord sysMessageRecord) + { + startPage(); + List list = sysMessageRecordService.selectSysMessageRecordList(sysMessageRecord); + return getDataTable(list); + } + + /** + * 导出消息接收记录列表 + */ + @PreAuthorize("@ss.hasPermi('system:sysMessageRecord:export')") + @Log(title = "消息接收记录", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, SysMessageRecord sysMessageRecord) + { + List list = sysMessageRecordService.selectSysMessageRecordList(sysMessageRecord); + ExcelUtil util = new ExcelUtil(SysMessageRecord.class); + util.exportExcel(response, list, "消息接收记录数据"); + } + + /** + * 获取消息接收记录详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:sysMessageRecord:query')") + @GetMapping(value = "/{messageRecordId}") + public AjaxResult getInfo(@PathVariable("messageRecordId") Long messageRecordId) + { + return success(sysMessageRecordService.selectSysMessageRecordByMessageRecordId(messageRecordId)); + } + + /** + * 新增消息接收记录 + */ + @PreAuthorize("@ss.hasPermi('system:sysMessageRecord:add')") + @Log(title = "消息接收记录", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SysMessageRecord sysMessageRecord) + { + return toAjax(sysMessageRecordService.insertSysMessageRecord(sysMessageRecord)); + } + + /** + * 修改消息接收记录 + */ + @PreAuthorize("@ss.hasPermi('system:sysMessageRecord:edit')") + @Log(title = "消息接收记录", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SysMessageRecord sysMessageRecord) + { + return toAjax(sysMessageRecordService.updateSysMessageRecord(sysMessageRecord)); + } + + /** + * 删除消息接收记录 + */ + @PreAuthorize("@ss.hasPermi('system:sysMessageRecord:remove')") + @Log(title = "消息接收记录", businessType = BusinessType.DELETE) + @DeleteMapping("/{messageRecordIds}") + public AjaxResult remove(@PathVariable Long[] messageRecordIds) + { + return toAjax(sysMessageRecordService.deleteSysMessageRecordByMessageRecordIds(messageRecordIds)); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/DailyUser.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/DailyUser.java new file mode 100644 index 00000000..d17b6e05 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/DailyUser.java @@ -0,0 +1,140 @@ +package com.ruoyi.system.domain; + +import java.time.LocalDate; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * userDaily对象 daily_user + * + * @author 昊天 + * @date 2024-11-04 + */ +public class DailyUser extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** id */ + private Long dailyUserId; + + /** 用户id */ + @Excel(name = "用户id") + private Long userId; + + /** 在线时长 */ + @Excel(name = "在线时长") + private Long onlineTime; + + /** MR在线时长 */ + @Excel(name = "MR在线时长") + private Long mrTime; + + /** 每天消费 */ + @Excel(name = "每天消费") + private Long consumption; + + /** 上传内容数 */ + @Excel(name = "上传内容数") + private Long tWork; + + /** 每天时间(记录到天就行) */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "每天时间(记录到天就行)", width = 30, dateFormat = "yyyy-MM-dd") + private LocalDate date; + + /** 删除标志 */ + private String delFlag; + + public void setDailyUserId(Long dailyUserId) + { + this.dailyUserId = dailyUserId; + } + + public Long getDailyUserId() + { + return dailyUserId; + } + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getUserId() + { + return userId; + } + public void setOnlineTime(Long onlineTime) + { + this.onlineTime = onlineTime; + } + + public Long getOnlineTime() + { + return onlineTime; + } + public void setMrTime(Long mrTime) + { + this.mrTime = mrTime; + } + + public Long getMrTime() + { + return mrTime; + } + public void setConsumption(Long consumption) + { + this.consumption = consumption; + } + + public Long getConsumption() + { + return consumption; + } + public void settWork(Long tWork) + { + this.tWork = tWork; + } + + public Long gettWork() + { + return tWork; + } + public void setDate(LocalDate date) + { + this.date = date; + } + + public LocalDate getDate() + { + return date; + } + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getDelFlag() + { + return delFlag; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("dailyUserId", getDailyUserId()) + .append("userId", getUserId()) + .append("onlineTime", getOnlineTime()) + .append("mrTime", getMrTime()) + .append("consumption", getConsumption()) + .append("tWork", gettWork()) + .append("createTime", getCreateTime()) + .append("updateTime", getUpdateTime()) + .append("date", getDate()) + .append("delFlag", getDelFlag()) + .toString(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/HeartbeatMessage.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/HeartbeatMessage.java new file mode 100644 index 00000000..2ebc65c0 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/HeartbeatMessage.java @@ -0,0 +1,22 @@ +package com.ruoyi.system.domain; + +import lombok.Data; + + +public class HeartbeatMessage { + private Long userId; + private Long timestamp; + + public Long getUserId() { + return userId; + } + public void setUserId(Long userId) { + this.userId = userId; + } + public Long getTimestamp() { + return timestamp; + } + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/HeartbeatResponse.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/HeartbeatResponse.java new file mode 100644 index 00000000..e4b154c3 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/HeartbeatResponse.java @@ -0,0 +1,28 @@ +package com.ruoyi.system.domain; + +public class HeartbeatResponse { + private Long timestamp; + private String status; + + public HeartbeatResponse(Long timestamp, String status) { + this.timestamp = timestamp; + this.status = status; + } + + // getter和setter + public Long getTimestamp() { + return timestamp; + } + + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/StUser.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/StUser.java new file mode 100644 index 00000000..ba3513c9 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/StUser.java @@ -0,0 +1,169 @@ +package com.ruoyi.system.domain; + +import java.time.LocalDate; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 用户7/30天统计数据对象 st_user + * + * @author haotian + * @date 2024-11-04 + */ +public class StUser extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 用户ID */ + private Long userId; + + /** 用户近7天在线时长 */ + @Excel(name = "用户近7天在线时长") + private Long seOnlineTime; + + /** 用户近30天在线时长 */ + @Excel(name = "用户近30天在线时长") + private Long thOnlineTime; + + /** 用户近7天MR在线时长 */ + @Excel(name = "用户近7天MR在线时长") + private Long seMrTime; + + /** 用户近30天MR在线时长(注意:原语句中defult应为default) */ + @Excel(name = "用户近30天MR在线时长", readConverterExp = "注=意:原语句中defult应为default") + private Long thMrTime; + + /** 用户近7天消费 */ + @Excel(name = "用户近7天消费") + private Long seConsumption; + + /** 用户近30天消费 */ + @Excel(name = "用户近30天消费") + private Long thConsumption; + + /** 用户近7天上传内容数 */ + @Excel(name = "用户近7天上传内容数") + private Long seWork; + + /** 用户近30天上传内容数(注意:原语句中2o应为20) */ + @Excel(name = "用户近30天上传内容数", readConverterExp = "注=意:原语句中2o应为20") + private Long thWork; + + /** 日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "日期", width = 30, dateFormat = "yyyy-MM-dd") + private LocalDate date; + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getUserId() + { + return userId; + } + public void setSeOnlineTime(Long seOnlineTime) + { + this.seOnlineTime = seOnlineTime; + } + + public Long getSeOnlineTime() + { + return seOnlineTime; + } + public void setThOnlineTime(Long thOnlineTime) + { + this.thOnlineTime = thOnlineTime; + } + + public Long getThOnlineTime() + { + return thOnlineTime; + } + public void setSeMrTime(Long seMrTime) + { + this.seMrTime = seMrTime; + } + + public Long getSeMrTime() + { + return seMrTime; + } + public void setThMrTime(Long thMrTime) + { + this.thMrTime = thMrTime; + } + + public Long getThMrTime() + { + return thMrTime; + } + public void setSeConsumption(Long seConsumption) + { + this.seConsumption = seConsumption; + } + + public Long getSeConsumption() + { + return seConsumption; + } + public void setThConsumption(Long thConsumption) + { + this.thConsumption = thConsumption; + } + + public Long getThConsumption() + { + return thConsumption; + } + public void setSeWork(Long seWork) + { + this.seWork = seWork; + } + + public Long getSeWork() + { + return seWork; + } + public void setThWork(Long thWork) + { + this.thWork = thWork; + } + + public Long getThWork() + { + return thWork; + } + public void setDate(LocalDate date) + { + this.date = date; + } + + public LocalDate getDate() + { + return date; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("seOnlineTime", getSeOnlineTime()) + .append("thOnlineTime", getThOnlineTime()) + .append("seMrTime", getSeMrTime()) + .append("thMrTime", getThMrTime()) + .append("seConsumption", getSeConsumption()) + .append("thConsumption", getThConsumption()) + .append("seWork", getSeWork()) + .append("thWork", getThWork()) + .append("createTime", getCreateTime()) + .append("updateTime", getUpdateTime()) + .append("date", getDate()) + .toString(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessage.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessage.java new file mode 100644 index 00000000..beea3b7b --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessage.java @@ -0,0 +1,124 @@ +package com.ruoyi.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 系统消息对象 sys_message + * + * @author haotian + * @date 2024-11-04 + */ +public class SysMessage extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 消息id */ + private Long messageId; + + /** 消息发送者id */ + @Excel(name = "消息发送者id") + private Long sendUserId; + + /** 消息接收者id */ + @Excel(name = "消息接收者id") + private Long receiveUserId; + + /** 消息内容 */ + @Excel(name = "消息内容") + private String messageContent; + + /** 标签 */ + @Excel(name = "标签") + private String messageType; + + /** 状态 */ + @Excel(name = "状态") + private String messageStatus; + + /** 删除标志(0代表存在, */ + private String delFlag; + + public void setMessageId(Long messageId) + { + this.messageId = messageId; + } + + public Long getMessageId() + { + return messageId; + } + public void setSendUserId(Long sendUserId) + { + this.sendUserId = sendUserId; + } + + public Long getSendUserId() + { + return sendUserId; + } + public void setReceiveUserId(Long receiveUserId) + { + this.receiveUserId = receiveUserId; + } + + public Long getReceiveUserId() + { + return receiveUserId; + } + public void setMessageContent(String messageContent) + { + this.messageContent = messageContent; + } + + public String getMessageContent() + { + return messageContent; + } + public void setMessageType(String messageType) + { + this.messageType = messageType; + } + + public String getMessageType() + { + return messageType; + } + public void setMessageStatus(String messageStatus) + { + this.messageStatus = messageStatus; + } + + public String getMessageStatus() + { + return messageStatus; + } + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getDelFlag() + { + return delFlag; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("messageId", getMessageId()) + .append("sendUserId", getSendUserId()) + .append("receiveUserId", getReceiveUserId()) + .append("messageContent", getMessageContent()) + .append("createTime", getCreateTime()) + .append("createBy", getCreateBy()) + .append("messageType", getMessageType()) + .append("updateTime", getUpdateTime()) + .append("updateBy", getUpdateBy()) + .append("messageStatus", getMessageStatus()) + .append("delFlag", getDelFlag()) + .toString(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessageRecord.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessageRecord.java new file mode 100644 index 00000000..b8fd3a7f --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessageRecord.java @@ -0,0 +1,99 @@ +package com.ruoyi.system.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 消息接收记录对象 sys_message_record + * + * @author haotian + * @date 2024-11-04 + */ +public class SysMessageRecord extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 主键自增,消息接收记录的唯一标识 */ + private Long messageRecordId; + + /** 消息id */ + @Excel(name = "消息id") + private Long messageId; + + /** 用户id,表示接收消息的用户 */ + @Excel(name = "用户id,表示接收消息的用户") + private Long userId; + + /** 阅读状态 +a.0 */ + @Excel(name = "阅读状态") + private String isRead; + + /** 阅读时间,当用户阅读消息时记录的时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "阅读时间,当用户阅读消息时记录的时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date readTime; + + public void setMessageRecordId(Long messageRecordId) + { + this.messageRecordId = messageRecordId; + } + + public Long getMessageRecordId() + { + return messageRecordId; + } + public void setMessageId(Long messageId) + { + this.messageId = messageId; + } + + public Long getMessageId() + { + return messageId; + } + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getUserId() + { + return userId; + } + public void setIsRead(String isRead) + { + this.isRead = isRead; + } + + public String getIsRead() + { + return isRead; + } + public void setReadTime(Date readTime) + { + this.readTime = readTime; + } + + public Date getReadTime() + { + return readTime; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("messageRecordId", getMessageRecordId()) + .append("messageId", getMessageId()) + .append("userId", getUserId()) + .append("isRead", getIsRead()) + .append("readTime", getReadTime()) + .append("createTime", getCreateTime()) + .append("updateTime", getUpdateTime()) + .toString(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnlineStats.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnlineStats.java new file mode 100644 index 00000000..0cfcb0b2 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnlineStats.java @@ -0,0 +1,18 @@ +package com.ruoyi.system.domain; + + +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +public class SysUserOnlineStats extends BaseEntity { +// private Long id; + private Long userId; + private Date statsDate; + private Long last7daysTime; + private Long last30daysTime; +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnlineTime.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnlineTime.java new file mode 100644 index 00000000..c859c8b9 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnlineTime.java @@ -0,0 +1,75 @@ +package com.ruoyi.system.domain; + +import java.util.Date; + +public class SysUserOnlineTime { + private Long id; + private Long userId; + private Date onlineDate; + private Long onlineTime; + private Date firstLoginTime; + private Date lastLogoutTime; + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + public Long getUserId() { + return userId; + } + public void setUserId(Long userId) { + this.userId = userId; + } + public Date getOnlineDate() { + return onlineDate; + } + public void setOnlineDate(Date onlineDate) { + this.onlineDate = onlineDate; + } + public Long getOnlineTime() { + return onlineTime; + } + public void setOnlineTime(Long onlineTime) { + this.onlineTime = onlineTime; + } + public Date getFirstLoginTime() { + return firstLoginTime; + } + public void setFirstLoginTime(Date firstLoginTime) { + this.firstLoginTime = firstLoginTime; + } + public Date getLastLogoutTime() { + return lastLogoutTime; + } + public void setLastLogoutTime(Date lastLogoutTime) { + this.lastLogoutTime = lastLogoutTime; + } + public void updateUserHeartbeat(Long userId) { + this.userId = userId; + this.onlineDate = new Date(); + } + public void updateOnlineTime(Long onlineTime) { + this.onlineTime = onlineTime; + } + public void updateFirstLoginTime(Date firstLoginTime) { + this.firstLoginTime = firstLoginTime; + } + public void updateLastLogoutTime(Date lastLogoutTime) { + this.lastLogoutTime = lastLogoutTime; + } + public void updateOnlineDate(Date onlineDate) { + this.onlineDate = onlineDate; + } + public String toString() { + return new StringBuilder() + .append("id: ").append(id) + .append(", userId: ").append(userId) + .append(", onlineDate: ").append(onlineDate) + .append(", onlineTime: ").append(onlineTime) + .append(", firstLoginTime: ").append(firstLoginTime) + .append(", lastLogoutTime: ").append(lastLogoutTime) + .toString(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/DailyUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/DailyUserMapper.java new file mode 100644 index 00000000..2651025e --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/DailyUserMapper.java @@ -0,0 +1,70 @@ +package com.ruoyi.system.mapper; + +import java.time.LocalDate; +import java.util.Date; +import java.util.List; +import com.ruoyi.system.domain.DailyUser; +import com.ruoyi.system.domain.SysUserOnlineTime; +import org.apache.ibatis.annotations.Param; + +/** + * userDailyMapper接口 + * + * @author 昊天 + * @date 2024-11-04 + */ +public interface DailyUserMapper +{ + /** + * 查询userDaily + * + * @param dailyUserId userDaily主键 + * @return userDaily + */ + public DailyUser selectDailyUserByDailyUserId(Long dailyUserId); + + /** + * 查询userDaily列表 + * + * @param dailyUser userDaily + * @return userDaily集合 + */ + public List selectDailyUserList(DailyUser dailyUser); + + /** + * 新增userDaily + * + * @param dailyUser userDaily + * @return 结果 + */ + public int insertDailyUser(DailyUser dailyUser); + + /** + * 修改userDaily + * + * @param dailyUser userDaily + * @return 结果 + */ + public int updateDailyUser(DailyUser dailyUser); + + + public int updateByUserIdAndDate(@Param("onlineTime")Long onlineTime, @Param("userId") Long userId, @Param("date") LocalDate date, @Param("updateTime") Date updateTime); + + /** + * 删除userDaily + * + * @param dailyUserId userDaily主键 + * @return 结果 + */ + public int deleteDailyUserByDailyUserId(Long dailyUserId); + + /** + * 批量删除userDaily + * + * @param dailyUserIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteDailyUserByDailyUserIds(Long[] dailyUserIds); + + public DailyUser selectByUserIdAndDate(@Param("userId") Long userId, @Param("date") LocalDate date); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/StUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/StUserMapper.java new file mode 100644 index 00000000..7150cb3a --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/StUserMapper.java @@ -0,0 +1,63 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.StUser; + +/** + * 用户7/30天统计数据Mapper接口 + * + * @author haotian + * @date 2024-11-04 + */ +public interface StUserMapper +{ + /** + * 查询用户7/30天统计数据 + * + * @param userId 用户7/30天统计数据主键 + * @return 用户7/30天统计数据 + */ + public StUser selectStUserByUserId(Long userId); + + /** + * 查询用户7/30天统计数据列表 + * + * @param stUser 用户7/30天统计数据 + * @return 用户7/30天统计数据集合 + */ + public List selectStUserList(StUser stUser); + + /** + * 新增用户7/30天统计数据 + * + * @param stUser 用户7/30天统计数据 + * @return 结果 + */ + public int insertStUser(StUser stUser); + + /** + * 修改用户7/30天统计数据 + * + * @param stUser 用户7/30天统计数据 + * @return 结果 + */ + public int updateStUser(StUser stUser); + + /** + * 删除用户7/30天统计数据 + * + * @param userId 用户7/30天统计数据主键 + * @return 结果 + */ + public int deleteStUserByUserId(Long userId); + + /** + * 批量删除用户7/30天统计数据 + * + * @param userIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteStUserByUserIds(Long[] userIds); + + public List getAllUserIds(); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageMapper.java new file mode 100644 index 00000000..e5e7d8a7 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageMapper.java @@ -0,0 +1,61 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysMessage; + +/** + * 系统消息Mapper接口 + * + * @author haotian + * @date 2024-11-04 + */ +public interface SysMessageMapper +{ + /** + * 查询系统消息 + * + * @param messageId 系统消息主键 + * @return 系统消息 + */ + public SysMessage selectSysMessageByMessageId(Long messageId); + + /** + * 查询系统消息列表 + * + * @param sysMessage 系统消息 + * @return 系统消息集合 + */ + public List selectSysMessageList(SysMessage sysMessage); + + /** + * 新增系统消息 + * + * @param sysMessage 系统消息 + * @return 结果 + */ + public int insertSysMessage(SysMessage sysMessage); + + /** + * 修改系统消息 + * + * @param sysMessage 系统消息 + * @return 结果 + */ + public int updateSysMessage(SysMessage sysMessage); + + /** + * 删除系统消息 + * + * @param messageId 系统消息主键 + * @return 结果 + */ + public int deleteSysMessageByMessageId(Long messageId); + + /** + * 批量删除系统消息 + * + * @param messageIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSysMessageByMessageIds(Long[] messageIds); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageRecordMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageRecordMapper.java new file mode 100644 index 00000000..38d113fd --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageRecordMapper.java @@ -0,0 +1,61 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysMessageRecord; + +/** + * 消息接收记录Mapper接口 + * + * @author haotian + * @date 2024-11-04 + */ +public interface SysMessageRecordMapper +{ + /** + * 查询消息接收记录 + * + * @param messageRecordId 消息接收记录主键 + * @return 消息接收记录 + */ + public SysMessageRecord selectSysMessageRecordByMessageRecordId(Long messageRecordId); + + /** + * 查询消息接收记录列表 + * + * @param sysMessageRecord 消息接收记录 + * @return 消息接收记录集合 + */ + public List selectSysMessageRecordList(SysMessageRecord sysMessageRecord); + + /** + * 新增消息接收记录 + * + * @param sysMessageRecord 消息接收记录 + * @return 结果 + */ + public int insertSysMessageRecord(SysMessageRecord sysMessageRecord); + + /** + * 修改消息接收记录 + * + * @param sysMessageRecord 消息接收记录 + * @return 结果 + */ + public int updateSysMessageRecord(SysMessageRecord sysMessageRecord); + + /** + * 删除消息接收记录 + * + * @param messageRecordId 消息接收记录主键 + * @return 结果 + */ + public int deleteSysMessageRecordByMessageRecordId(Long messageRecordId); + + /** + * 批量删除消息接收记录 + * + * @param messageRecordIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSysMessageRecordByMessageRecordIds(Long[] messageRecordIds); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IDailyUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IDailyUserService.java new file mode 100644 index 00000000..a0758905 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IDailyUserService.java @@ -0,0 +1,61 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.DailyUser; + +/** + * userDailyService接口 + * + * @author 昊天 + * @date 2024-11-04 + */ +public interface IDailyUserService +{ + /** + * 查询userDaily + * + * @param dailyUserId userDaily主键 + * @return userDaily + */ + public DailyUser selectDailyUserByDailyUserId(Long dailyUserId); + + /** + * 查询userDaily列表 + * + * @param dailyUser userDaily + * @return userDaily集合 + */ + public List selectDailyUserList(DailyUser dailyUser); + + /** + * 新增userDaily + * + * @param dailyUser userDaily + * @return 结果 + */ + public int insertDailyUser(DailyUser dailyUser); + + /** + * 修改userDaily + * + * @param dailyUser userDaily + * @return 结果 + */ + public int updateDailyUser(DailyUser dailyUser); + + /** + * 批量删除userDaily + * + * @param dailyUserIds 需要删除的userDaily主键集合 + * @return 结果 + */ + public int deleteDailyUserByDailyUserIds(Long[] dailyUserIds); + + /** + * 删除userDaily信息 + * + * @param dailyUserId userDaily主键 + * @return 结果 + */ + public int deleteDailyUserByDailyUserId(Long dailyUserId); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IStUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IStUserService.java new file mode 100644 index 00000000..75e24d4e --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IStUserService.java @@ -0,0 +1,61 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.StUser; + +/** + * 用户7/30天统计数据Service接口 + * + * @author haotian + * @date 2024-11-04 + */ +public interface IStUserService +{ + /** + * 查询用户7/30天统计数据 + * + * @param userId 用户7/30天统计数据主键 + * @return 用户7/30天统计数据 + */ + public StUser selectStUserByUserId(Long userId); + + /** + * 查询用户7/30天统计数据列表 + * + * @param stUser 用户7/30天统计数据 + * @return 用户7/30天统计数据集合 + */ + public List selectStUserList(StUser stUser); + + /** + * 新增用户7/30天统计数据 + * + * @param stUser 用户7/30天统计数据 + * @return 结果 + */ + public int insertStUser(StUser stUser); + + /** + * 修改用户7/30天统计数据 + * + * @param stUser 用户7/30天统计数据 + * @return 结果 + */ + public int updateStUser(StUser stUser); + + /** + * 批量删除用户7/30天统计数据 + * + * @param userIds 需要删除的用户7/30天统计数据主键集合 + * @return 结果 + */ + public int deleteStUserByUserIds(Long[] userIds); + + /** + * 删除用户7/30天统计数据信息 + * + * @param userId 用户7/30天统计数据主键 + * @return 结果 + */ + public int deleteStUserByUserId(Long userId); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageRecordService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageRecordService.java new file mode 100644 index 00000000..3705b555 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageRecordService.java @@ -0,0 +1,61 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.SysMessageRecord; + +/** + * 消息接收记录Service接口 + * + * @author haotian + * @date 2024-11-04 + */ +public interface ISysMessageRecordService +{ + /** + * 查询消息接收记录 + * + * @param messageRecordId 消息接收记录主键 + * @return 消息接收记录 + */ + public SysMessageRecord selectSysMessageRecordByMessageRecordId(Long messageRecordId); + + /** + * 查询消息接收记录列表 + * + * @param sysMessageRecord 消息接收记录 + * @return 消息接收记录集合 + */ + public List selectSysMessageRecordList(SysMessageRecord sysMessageRecord); + + /** + * 新增消息接收记录 + * + * @param sysMessageRecord 消息接收记录 + * @return 结果 + */ + public int insertSysMessageRecord(SysMessageRecord sysMessageRecord); + + /** + * 修改消息接收记录 + * + * @param sysMessageRecord 消息接收记录 + * @return 结果 + */ + public int updateSysMessageRecord(SysMessageRecord sysMessageRecord); + + /** + * 批量删除消息接收记录 + * + * @param messageRecordIds 需要删除的消息接收记录主键集合 + * @return 结果 + */ + public int deleteSysMessageRecordByMessageRecordIds(Long[] messageRecordIds); + + /** + * 删除消息接收记录信息 + * + * @param messageRecordId 消息接收记录主键 + * @return 结果 + */ + public int deleteSysMessageRecordByMessageRecordId(Long messageRecordId); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageService.java new file mode 100644 index 00000000..0d0ef9b8 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageService.java @@ -0,0 +1,61 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.SysMessage; + +/** + * 系统消息Service接口 + * + * @author haotian + * @date 2024-11-04 + */ +public interface ISysMessageService +{ + /** + * 查询系统消息 + * + * @param messageId 系统消息主键 + * @return 系统消息 + */ + public SysMessage selectSysMessageByMessageId(Long messageId); + + /** + * 查询系统消息列表 + * + * @param sysMessage 系统消息 + * @return 系统消息集合 + */ + public List selectSysMessageList(SysMessage sysMessage); + + /** + * 新增系统消息 + * + * @param sysMessage 系统消息 + * @return 结果 + */ + public int insertSysMessage(SysMessage sysMessage); + + /** + * 修改系统消息 + * + * @param sysMessage 系统消息 + * @return 结果 + */ + public int updateSysMessage(SysMessage sysMessage); + + /** + * 批量删除系统消息 + * + * @param messageIds 需要删除的系统消息主键集合 + * @return 结果 + */ + public int deleteSysMessageByMessageIds(Long[] messageIds); + + /** + * 删除系统消息信息 + * + * @param messageId 系统消息主键 + * @return 结果 + */ + public int deleteSysMessageByMessageId(Long messageId); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineTimeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineTimeService.java new file mode 100644 index 00000000..7033f7f8 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineTimeService.java @@ -0,0 +1,19 @@ +package com.ruoyi.system.service; + +import com.ruoyi.system.domain.DailyUser; +import com.ruoyi.system.domain.StUser; +import com.ruoyi.system.domain.SysUserOnlineStats; +import com.ruoyi.system.domain.SysUserOnlineTime; + +import java.util.Date; + +public interface ISysUserOnlineTimeService { + public void recordUserLogin(Long userId); + public int recordUserLogout(Long userId); + public int updateUserHeartbeat(Long userId); +// DailyUser getUserDailyOnlineTime(Long userId); +// StUser getUserOnlineStats(Long userId); + public void calculateUserOnlineStats(); + + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DailyUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DailyUserServiceImpl.java new file mode 100644 index 00000000..565a7b6b --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DailyUserServiceImpl.java @@ -0,0 +1,96 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.system.mapper.DailyUserMapper; +import com.ruoyi.system.domain.DailyUser; +import com.ruoyi.system.service.IDailyUserService; + +/** + * userDailyService业务层处理 + * + * @author 昊天 + * @date 2024-11-04 + */ +@Service +public class DailyUserServiceImpl implements IDailyUserService +{ + @Autowired + private DailyUserMapper dailyUserMapper; + + /** + * 查询userDaily + * + * @param dailyUserId userDaily主键 + * @return userDaily + */ + @Override + public DailyUser selectDailyUserByDailyUserId(Long dailyUserId) + { + return dailyUserMapper.selectDailyUserByDailyUserId(dailyUserId); + } + + /** + * 查询userDaily列表 + * + * @param dailyUser userDaily + * @return userDaily + */ + @Override + public List selectDailyUserList(DailyUser dailyUser) + { + return dailyUserMapper.selectDailyUserList(dailyUser); + } + + /** + * 新增userDaily + * + * @param dailyUser userDaily + * @return 结果 + */ + @Override + public int insertDailyUser(DailyUser dailyUser) + { + dailyUser.setCreateTime(DateUtils.getNowDate()); + return dailyUserMapper.insertDailyUser(dailyUser); + } + + /** + * 修改userDaily + * + * @param dailyUser userDaily + * @return 结果 + */ + @Override + public int updateDailyUser(DailyUser dailyUser) + { + dailyUser.setUpdateTime(DateUtils.getNowDate()); + return dailyUserMapper.updateDailyUser(dailyUser); + } + + /** + * 批量删除userDaily + * + * @param dailyUserIds 需要删除的userDaily主键 + * @return 结果 + */ + @Override + public int deleteDailyUserByDailyUserIds(Long[] dailyUserIds) + { + return dailyUserMapper.deleteDailyUserByDailyUserIds(dailyUserIds); + } + + /** + * 删除userDaily信息 + * + * @param dailyUserId userDaily主键 + * @return 结果 + */ + @Override + public int deleteDailyUserByDailyUserId(Long dailyUserId) + { + return dailyUserMapper.deleteDailyUserByDailyUserId(dailyUserId); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StUserServiceImpl.java new file mode 100644 index 00000000..b864f4f6 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StUserServiceImpl.java @@ -0,0 +1,96 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.system.mapper.StUserMapper; +import com.ruoyi.system.domain.StUser; +import com.ruoyi.system.service.IStUserService; + +/** + * 用户7/30天统计数据Service业务层处理 + * + * @author haotian + * @date 2024-11-04 + */ +@Service +public class StUserServiceImpl implements IStUserService +{ + @Autowired + private StUserMapper stUserMapper; + + /** + * 查询用户7/30天统计数据 + * + * @param userId 用户7/30天统计数据主键 + * @return 用户7/30天统计数据 + */ + @Override + public StUser selectStUserByUserId(Long userId) + { + return stUserMapper.selectStUserByUserId(userId); + } + + /** + * 查询用户7/30天统计数据列表 + * + * @param stUser 用户7/30天统计数据 + * @return 用户7/30天统计数据 + */ + @Override + public List selectStUserList(StUser stUser) + { + return stUserMapper.selectStUserList(stUser); + } + + /** + * 新增用户7/30天统计数据 + * + * @param stUser 用户7/30天统计数据 + * @return 结果 + */ + @Override + public int insertStUser(StUser stUser) + { + stUser.setCreateTime(DateUtils.getNowDate()); + return stUserMapper.insertStUser(stUser); + } + + /** + * 修改用户7/30天统计数据 + * + * @param stUser 用户7/30天统计数据 + * @return 结果 + */ + @Override + public int updateStUser(StUser stUser) + { + stUser.setUpdateTime(DateUtils.getNowDate()); + return stUserMapper.updateStUser(stUser); + } + + /** + * 批量删除用户7/30天统计数据 + * + * @param userIds 需要删除的用户7/30天统计数据主键 + * @return 结果 + */ + @Override + public int deleteStUserByUserIds(Long[] userIds) + { + return stUserMapper.deleteStUserByUserIds(userIds); + } + + /** + * 删除用户7/30天统计数据信息 + * + * @param userId 用户7/30天统计数据主键 + * @return 结果 + */ + @Override + public int deleteStUserByUserId(Long userId) + { + return stUserMapper.deleteStUserByUserId(userId); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageRecordServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageRecordServiceImpl.java new file mode 100644 index 00000000..e923ef5a --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageRecordServiceImpl.java @@ -0,0 +1,96 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.system.mapper.SysMessageRecordMapper; +import com.ruoyi.system.domain.SysMessageRecord; +import com.ruoyi.system.service.ISysMessageRecordService; + +/** + * 消息接收记录Service业务层处理 + * + * @author haotian + * @date 2024-11-04 + */ +@Service +public class SysMessageRecordServiceImpl implements ISysMessageRecordService +{ + @Autowired + private SysMessageRecordMapper sysMessageRecordMapper; + + /** + * 查询消息接收记录 + * + * @param messageRecordId 消息接收记录主键 + * @return 消息接收记录 + */ + @Override + public SysMessageRecord selectSysMessageRecordByMessageRecordId(Long messageRecordId) + { + return sysMessageRecordMapper.selectSysMessageRecordByMessageRecordId(messageRecordId); + } + + /** + * 查询消息接收记录列表 + * + * @param sysMessageRecord 消息接收记录 + * @return 消息接收记录 + */ + @Override + public List selectSysMessageRecordList(SysMessageRecord sysMessageRecord) + { + return sysMessageRecordMapper.selectSysMessageRecordList(sysMessageRecord); + } + + /** + * 新增消息接收记录 + * + * @param sysMessageRecord 消息接收记录 + * @return 结果 + */ + @Override + public int insertSysMessageRecord(SysMessageRecord sysMessageRecord) + { + sysMessageRecord.setCreateTime(DateUtils.getNowDate()); + return sysMessageRecordMapper.insertSysMessageRecord(sysMessageRecord); + } + + /** + * 修改消息接收记录 + * + * @param sysMessageRecord 消息接收记录 + * @return 结果 + */ + @Override + public int updateSysMessageRecord(SysMessageRecord sysMessageRecord) + { + sysMessageRecord.setUpdateTime(DateUtils.getNowDate()); + return sysMessageRecordMapper.updateSysMessageRecord(sysMessageRecord); + } + + /** + * 批量删除消息接收记录 + * + * @param messageRecordIds 需要删除的消息接收记录主键 + * @return 结果 + */ + @Override + public int deleteSysMessageRecordByMessageRecordIds(Long[] messageRecordIds) + { + return sysMessageRecordMapper.deleteSysMessageRecordByMessageRecordIds(messageRecordIds); + } + + /** + * 删除消息接收记录信息 + * + * @param messageRecordId 消息接收记录主键 + * @return 结果 + */ + @Override + public int deleteSysMessageRecordByMessageRecordId(Long messageRecordId) + { + return sysMessageRecordMapper.deleteSysMessageRecordByMessageRecordId(messageRecordId); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageServiceImpl.java new file mode 100644 index 00000000..f417f69d --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageServiceImpl.java @@ -0,0 +1,96 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.system.mapper.SysMessageMapper; +import com.ruoyi.system.domain.SysMessage; +import com.ruoyi.system.service.ISysMessageService; + +/** + * 系统消息Service业务层处理 + * + * @author haotian + * @date 2024-11-04 + */ +@Service +public class SysMessageServiceImpl implements ISysMessageService +{ + @Autowired + private SysMessageMapper sysMessageMapper; + + /** + * 查询系统消息 + * + * @param messageId 系统消息主键 + * @return 系统消息 + */ + @Override + public SysMessage selectSysMessageByMessageId(Long messageId) + { + return sysMessageMapper.selectSysMessageByMessageId(messageId); + } + + /** + * 查询系统消息列表 + * + * @param sysMessage 系统消息 + * @return 系统消息 + */ + @Override + public List selectSysMessageList(SysMessage sysMessage) + { + return sysMessageMapper.selectSysMessageList(sysMessage); + } + + /** + * 新增系统消息 + * + * @param sysMessage 系统消息 + * @return 结果 + */ + @Override + public int insertSysMessage(SysMessage sysMessage) + { + sysMessage.setCreateTime(DateUtils.getNowDate()); + return sysMessageMapper.insertSysMessage(sysMessage); + } + + /** + * 修改系统消息 + * + * @param sysMessage 系统消息 + * @return 结果 + */ + @Override + public int updateSysMessage(SysMessage sysMessage) + { + sysMessage.setUpdateTime(DateUtils.getNowDate()); + return sysMessageMapper.updateSysMessage(sysMessage); + } + + /** + * 批量删除系统消息 + * + * @param messageIds 需要删除的系统消息主键 + * @return 结果 + */ + @Override + public int deleteSysMessageByMessageIds(Long[] messageIds) + { + return sysMessageMapper.deleteSysMessageByMessageIds(messageIds); + } + + /** + * 删除系统消息信息 + * + * @param messageId 系统消息主键 + * @return 结果 + */ + @Override + public int deleteSysMessageByMessageId(Long messageId) + { + return sysMessageMapper.deleteSysMessageByMessageId(messageId); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineTimeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineTimeServiceImpl.java new file mode 100644 index 00000000..9058314d --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineTimeServiceImpl.java @@ -0,0 +1,226 @@ +package com.ruoyi.system.service.impl; + +import com.ruoyi.system.domain.DailyUser; +import com.ruoyi.system.domain.StUser; +import com.ruoyi.system.domain.SysUserOnlineTime; +import com.ruoyi.system.mapper.DailyUserMapper; +import com.ruoyi.system.mapper.StUserMapper; +import com.ruoyi.system.service.ISysUserOnlineTimeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +//import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +import java.util.Date; +import java.util.prefs.BackingStoreException; + +@Service +public class SysUserOnlineTimeServiceImpl implements ISysUserOnlineTimeService { + + private final ConcurrentHashMap userLastHeartbeatMap = new ConcurrentHashMap<>(); + + @Autowired + private DailyUserMapper dailyUserMapper; + + @Autowired + private StUserMapper stUserMapper; + + @Override + public void recordUserLogin(Long userId){ + + System.out.println("用户登录" + userId); + + Date now = new Date(); + LocalDate localNow = LocalDate.now(); + //若当前用户今天没登录过,每天登录中用户为null + DailyUser dailyUser = dailyUserMapper.selectByUserIdAndDate(userId, localNow); + if (dailyUser == null){ + //初始化daily_user用户数据 + dailyUser = new DailyUser(); + dailyUser.setUserId(userId); + dailyUser.setOnlineTime(0L); + dailyUser.setMrTime(0L); + dailyUser.setConsumption(0L); + dailyUser.settWork(0L); + dailyUser.setCreateTime(now); + dailyUser.setUpdateTime(now); + // 这里是用户每天的记录,所以日期只记录到天 + dailyUser.setDate(localNow); + + dailyUserMapper.insertDailyUser(dailyUser); + + } + //心跳初始化时间 + userLastHeartbeatMap.put(userId, now); + } + + //记录登出时间, 同时更新在线时间数据 + @Override + public int recordUserLogout(Long userId){ + + //先更新在线时间 + Date now = new Date(); + Date lastHeartbeat = userLastHeartbeatMap.get(userId); + if (lastHeartbeat != null){ + updateOnlineTime(userId, lastHeartbeat, now); + } + + //移除websocket中的心跳对. + userLastHeartbeatMap.remove(userId); + + System.out.println("用户退出时间:" + now); + return 1; + } + + // 更新心跳时间 + @Override + public int updateUserHeartbeat(Long userId){ + + + Date now = new Date(); + Date lastHeartbeat = userLastHeartbeatMap.get(userId); + + System.out.println("上一次心跳时间:" + lastHeartbeat); + int back = 0; + //如果上一次心跳时间不为空 + if (lastHeartbeat != null){ + back = updateOnlineTime(userId, lastHeartbeat, now); + } + + userLastHeartbeatMap.put(userId, now); + System.out.println("更新用户心跳时间"); + return back; + } + + private int updateOnlineTime(Long userId, Date startTime, Date endTime){ + //-----------------------------------更新用户在线时间------------------------------------------ + // 获取开始时间的日期部分 + LocalDate startDate = startTime.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + + // 获取结束时间的日期部分 + LocalDate endDate = endTime.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + + // 根据今天的日期获取用户数据 + // 以开始时间作为查询的话,会导致若用户一直不退出,今天的在线时长会一直增加,能超出一天的总时长 + // 所以这里用结束时间查询,由于日期只记录到天,同一天开始和结束应该一样. + DailyUser dailyUser = dailyUserMapper.selectByUserIdAndDate(userId, endDate); + if (dailyUser != null){ + System.out.println("用户当天登录过"); + int back = updateSingleDayOnlineTime(userId, startTime, endTime); + return back; + + } + // 若更新时查不到用户记录-------------------用户登录时跨天了------------------------------------ + else{ + System.out.println("用户前一天登录,直到现在"); + //所以前一天的在线时长到 前一天的23:59:59 + Date firstDayEnd = Date.from(startDate.atTime(23, 59, 59) + .atZone(ZoneId.systemDefault()) + .toInstant()); + updateSingleDayOnlineTime(userId, startTime, firstDayEnd); + // 计算最后一天的在线时长(从当天开始00:00:00到结束时间) + Date lastDayStart = Date.from(endDate.atStartOfDay() + .atZone(ZoneId.systemDefault()) + .toInstant()); + + int back = updateSingleDayOnlineTime(userId, startTime, lastDayStart); + return back; + } + //----------------------------------------------end 更新用户在线时间----------------------------------------------- + + } + + private int updateSingleDayOnlineTime(Long userId, Date startTime, Date endTime) { + long duration = (endTime.getTime() - startTime.getTime()) / 1000; // 转换为秒 + + LocalDate startDate = startTime.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + + DailyUser dailyUser = dailyUserMapper.selectByUserIdAndDate(userId, startDate); + // 不跨天 + if (dailyUser != null) { + + System.out.println("不跨天"); + // 更新在线时长,使用userId和date作为条件 + int back = dailyUserMapper.updateByUserIdAndDate(dailyUser.getOnlineTime() + duration, userId, startDate, endTime); + return back; + //跨天的情况, + } else { + // 如果记录不存在,创建新记录 + dailyUser = new DailyUser(); + dailyUser.setUserId(userId); + dailyUser.setOnlineTime(0L); + dailyUser.setMrTime(0L); + dailyUser.setConsumption(0L); + dailyUser.settWork(0L); + dailyUser.setCreateTime(startTime); + // 这里是用户每天的记录,所以日期只记录到天 + dailyUser.setDate(startDate); + int back = dailyUserMapper.insertDailyUser(dailyUser); + int back2 = dailyUserMapper.updateByUserIdAndDate(duration, userId, startDate, endTime); + if (back2 == 0 || back == 0){ + return 0; + } + return 1; + + } + } + + //统计用户7/30天在线时长, 可以用定时任务,每天设置一个时间点计算 + @Override + public void calculateUserOnlineStats() { + + Date today = Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant()); + + //获取所有用户, 假设用户在创建账号时就在st_user表中创建数据 + List userIds = stUserMapper.getAllUserIds(); + + //计算每个用户的7/30天在线时长, 每天计算前7天的在线时间 + /* + * 近7天时间 = 当前近7天时间-7天前的时间+前1天时间 + * 今天 8月9日---计算8月8日的近7天时间------8月7日的近7天时间+8月8日的在线时间-8月1日的在线时间 + * */ + for(Long userId : userIds){ + + // 获取当前日期. 默认到天吧 + LocalDate now = LocalDate.now(); + + // 计算前1天、前2天和前8天的日期 + LocalDate oneDayAgo = now.minusDays(1); +// LocalDate twoDaysAgo = now.minusDays(2); + LocalDate eightDaysAgo = now.minusDays(8); + + DailyUser oneDayAgoUser = dailyUserMapper.selectByUserIdAndDate(userId, oneDayAgo); + Long oneDayAgoOnlineTime = oneDayAgoUser != null ? oneDayAgoUser.getOnlineTime() : 0L; + + DailyUser eightDaysAgoUser = dailyUserMapper.selectByUserIdAndDate(userId, eightDaysAgo); + Long eightDaysAgoOnlineTime = eightDaysAgoUser != null ? eightDaysAgoUser.getOnlineTime() : 0L; + + // st_user表中每个用户应该只有一行数据,所以直接通过userId来获取 + StUser stUser = stUserMapper.selectStUserByUserId(userId); + // 应该一定不会为null吧 + Long last7daysTime = stUser.getSeOnlineTime(); + + Long new7daysTime = last7daysTime + oneDayAgoOnlineTime - eightDaysAgoOnlineTime; + + //重写数据 + stUser.setSeOnlineTime(new7daysTime); + stUser.setUpdateTime(new Date()); + stUser.setDate(oneDayAgo); + + //更新数据库 + stUserMapper.updateStUser(stUser); + + } + } + +} diff --git a/ruoyi-system/src/main/resources/mapper/system/DailyUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/DailyUserMapper.xml new file mode 100644 index 00000000..43b164fb --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/DailyUserMapper.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + select daily_user_id, user_id, online_time, mr_time, consumption, t_work, create_time, update_time, date, del_flag from daily_user + + + + + + + + + + insert into daily_user + + user_id, + online_time, + mr_time, + consumption, + t_work, + create_time, + update_time, + date, + del_flag, + + + #{userId}, + #{onlineTime}, + #{mrTime}, + #{consumption}, + #{tWork}, + #{createTime}, + #{updateTime}, + #{date}, + #{delFlag}, + + + + + update daily_user + + user_id = #{userId}, + online_time = #{onlineTime}, + mr_time = #{mrTime}, + consumption = #{consumption}, + t_work = #{tWork}, + create_time = #{createTime}, + update_time = #{updateTime}, + date = #{date}, + del_flag = #{delFlag}, + + where daily_user_id = #{dailyUserId} + + + update daily_user + + online_time = #{onlineTime}, + update_time = #{updateTime}, + + where user_id = #{userId} and date = #{date} + + + + + delete from daily_user where daily_user_id = #{dailyUserId} + + + + delete from daily_user where daily_user_id in + + #{dailyUserId} + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/StUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/StUserMapper.xml new file mode 100644 index 00000000..f7ddef13 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/StUserMapper.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + select user_id, se_online_time, th_online_time, se_mr_time, th_mr_time, se_consumption, th_consumption, se_work, th_work, create_time, update_time, date from st_user + + + + + + + + + + insert into st_user + + se_online_time, + th_online_time, + se_mr_time, + th_mr_time, + se_consumption, + th_consumption, + se_work, + th_work, + create_time, + update_time, + date, + + + #{seOnlineTime}, + #{thOnlineTime}, + #{seMrTime}, + #{thMrTime}, + #{seConsumption}, + #{thConsumption}, + #{seWork}, + #{thWork}, + #{createTime}, + #{updateTime}, + #{date}, + + + + + update st_user + + se_online_time = #{seOnlineTime}, + th_online_time = #{thOnlineTime}, + se_mr_time = #{seMrTime}, + th_mr_time = #{thMrTime}, + se_consumption = #{seConsumption}, + th_consumption = #{thConsumption}, + se_work = #{seWork}, + th_work = #{thWork}, + create_time = #{createTime}, + update_time = #{updateTime}, + date = #{date}, + + where user_id = #{userId} + + + + delete from st_user where user_id = #{userId} + + + + delete from st_user where user_id in + + #{userId} + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysMessageMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysMessageMapper.xml new file mode 100644 index 00000000..13c48929 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysMessageMapper.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + select message_id, send_user_id, receive_user_id, message_content, create_time, create_by, message_type, update_time, update_by, message_status, del_flag from sys_message + + + + + + + + insert into sys_message + + send_user_id, + receive_user_id, + message_content, + create_time, + create_by, + message_type, + update_time, + update_by, + message_status, + del_flag, + + + #{sendUserId}, + #{receiveUserId}, + #{messageContent}, + #{createTime}, + #{createBy}, + #{messageType}, + #{updateTime}, + #{updateBy}, + #{messageStatus}, + #{delFlag}, + + + + + update sys_message + + send_user_id = #{sendUserId}, + receive_user_id = #{receiveUserId}, + message_content = #{messageContent}, + create_time = #{createTime}, + create_by = #{createBy}, + message_type = #{messageType}, + update_time = #{updateTime}, + update_by = #{updateBy}, + message_status = #{messageStatus}, + del_flag = #{delFlag}, + + where message_id = #{messageId} + + + + delete from sys_message where message_id = #{messageId} + + + + delete from sys_message where message_id in + + #{messageId} + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysMessageRecordMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysMessageRecordMapper.xml new file mode 100644 index 00000000..85ea7637 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysMessageRecordMapper.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + select message_record_id, message_id, user_id, is_read, read_time, create_time, update_time from sys_message_record + + + + + + + + insert into sys_message_record + + message_id, + user_id, + is_read, + read_time, + create_time, + update_time, + + + #{messageId}, + #{userId}, + #{isRead}, + #{readTime}, + #{createTime}, + #{updateTime}, + + + + + update sys_message_record + + message_id = #{messageId}, + user_id = #{userId}, + is_read = #{isRead}, + read_time = #{readTime}, + create_time = #{createTime}, + update_time = #{updateTime}, + + where message_record_id = #{messageRecordId} + + + + delete from sys_message_record where message_record_id = #{messageRecordId} + + + + delete from sys_message_record where message_record_id in + + #{messageRecordId} + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/UserInfoMapper.xml b/ruoyi-system/src/main/resources/mapper/system/UserInfoMapper.xml index 414160a6..bec00815 100644 --- a/ruoyi-system/src/main/resources/mapper/system/UserInfoMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/UserInfoMapper.xml @@ -98,10 +98,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" t_mr_time, t_online_time, t_consumption, - update_time - date_of_birth - back_ground - calculation_time + update_time, + date_of_birth, + back_ground, + calculation_time, #{userId},