通过socket实现记录用户在线时间。

This commit is contained in:
haotianmingyue 2024-11-06 15:31:01 +08:00
parent fff989548d
commit 9e10a89c80
42 changed files with 3109 additions and 245 deletions

View File

@ -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();
}
}

View File

@ -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");
// }
// }
//}
//
//

View File

@ -97,7 +97,7 @@ token:
# 令牌密钥
secret: abcdefghijklmnopqrstuvwxyz
# 令牌有效期默认30分钟1440 = 60*24
expireTime: 1440
expireTime: 43200
# MyBatis配置
mybatis:

View File

@ -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/**"

View File

@ -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;
}
/**
* 设置用户身份信息

View File

@ -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<UserLocation> 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());
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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");
// }
}

View File

@ -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);
// }
//}

View File

@ -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<String, Session> USERS = new ConcurrentHashMap<>();
// 保存用户ID和Session的映射
private static final Map<String, Session> USER_SESSIONS = new ConcurrentHashMap<>();
// 保存Session和用户ID的映射
private static final Map<String, String> 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<Map.Entry<String, Session>> entries = USERS.entrySet();
for (Map.Entry<String, Session> 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<String, Session> getUsers()
{
return USERS;
public static Session getSession(String userId) {
return USER_SESSIONS.get(userId);
}
/**
* 群发消息文本消息
*
* @param message 消息内容
*/
public static void sendMessageToUsersByText(String message)
{
Collection<Session> 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();
}
}

View File

@ -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<DailyUser> 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<DailyUser> list = dailyUserService.selectDailyUserList(dailyUser);
ExcelUtil<DailyUser> util = new ExcelUtil<DailyUser>(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));
}
}

View File

@ -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<StUser> 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<StUser> list = stUserService.selectStUserList(stUser);
ExcelUtil<StUser> util = new ExcelUtil<StUser>(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));
}
}

View File

@ -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<SysMessage> 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<SysMessage> list = sysMessageService.selectSysMessageList(sysMessage);
ExcelUtil<SysMessage> util = new ExcelUtil<SysMessage>(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));
}
}

View File

@ -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<SysMessageRecord> 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<SysMessageRecord> list = sysMessageRecordService.selectSysMessageRecordList(sysMessageRecord);
ExcelUtil<SysMessageRecord> util = new ExcelUtil<SysMessageRecord>(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));
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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<DailyUser> 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);
}

View File

@ -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<StUser> 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<Long> getAllUserIds();
}

View File

@ -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<SysMessage> 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);
}

View File

@ -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<SysMessageRecord> 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);
}

View File

@ -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<DailyUser> 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);
}

View File

@ -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<StUser> 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);
}

View File

@ -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<SysMessageRecord> 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);
}

View File

@ -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<SysMessage> 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);
}

View File

@ -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();
}

View File

@ -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<DailyUser> 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);
}
}

View File

@ -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<StUser> 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);
}
}

View File

@ -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<SysMessageRecord> 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);
}
}

View File

@ -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<SysMessage> 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);
}
}

View File

@ -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<Long, Date> 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<Long> 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);
}
}
}

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.DailyUserMapper">
<resultMap type="DailyUser" id="DailyUserResult">
<result property="dailyUserId" column="daily_user_id" />
<result property="userId" column="user_id" />
<result property="onlineTime" column="online_time" />
<result property="mrTime" column="mr_time" />
<result property="consumption" column="consumption" />
<result property="tWork" column="t_work" />
<result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" />
<result property="date" column="date" />
<result property="delFlag" column="del_flag" />
</resultMap>
<sql id="selectDailyUserVo">
select daily_user_id, user_id, online_time, mr_time, consumption, t_work, create_time, update_time, date, del_flag from daily_user
</sql>
<select id="selectDailyUserList" parameterType="DailyUser" resultMap="DailyUserResult">
<include refid="selectDailyUserVo"/>
<where>
<if test="userId != null "> and user_id = #{userId}</if>
<if test="onlineTime != null "> and online_time = #{onlineTime}</if>
<if test="mrTime != null "> and mr_time = #{mrTime}</if>
<if test="consumption != null "> and consumption = #{consumption}</if>
<if test="tWork != null "> and t_work = #{tWork}</if>
<if test="date != null "> and date = #{date}</if>
</where>
</select>
<select id="selectDailyUserByDailyUserId" parameterType="Long" resultMap="DailyUserResult">
<include refid="selectDailyUserVo"/>
where daily_user_id = #{dailyUserId}
</select>
<select id="selectByUserIdAndDate" resultMap="DailyUserResult">
select * from daily_user where user_id = #{userId} and date = #{date}
</select>
<insert id="insertDailyUser" parameterType="DailyUser" useGeneratedKeys="true" keyProperty="dailyUserId">
insert into daily_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="userId != null">user_id,</if>
<if test="onlineTime != null">online_time,</if>
<if test="mrTime != null">mr_time,</if>
<if test="consumption != null">consumption,</if>
<if test="tWork != null">t_work,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
<if test="date != null">date,</if>
<if test="delFlag != null">del_flag,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="userId != null">#{userId},</if>
<if test="onlineTime != null">#{onlineTime},</if>
<if test="mrTime != null">#{mrTime},</if>
<if test="consumption != null">#{consumption},</if>
<if test="tWork != null">#{tWork},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="date != null">#{date},</if>
<if test="delFlag != null">#{delFlag},</if>
</trim>
</insert>
<update id="updateDailyUser" parameterType="DailyUser">
update daily_user
<trim prefix="SET" suffixOverrides=",">
<if test="userId != null">user_id = #{userId},</if>
<if test="onlineTime != null">online_time = #{onlineTime},</if>
<if test="mrTime != null">mr_time = #{mrTime},</if>
<if test="consumption != null">consumption = #{consumption},</if>
<if test="tWork != null">t_work = #{tWork},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="date != null">date = #{date},</if>
<if test="delFlag != null">del_flag = #{delFlag},</if>
</trim>
where daily_user_id = #{dailyUserId}
</update>
<update id="updateByUserIdAndDate" parameterType="DailyUser">
update daily_user
<trim prefix="SET" suffixOverrides=",">
<if test="onlineTime != null">online_time = #{onlineTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where user_id = #{userId} and date = #{date}
</update>
<delete id="deleteDailyUserByDailyUserId" parameterType="Long">
delete from daily_user where daily_user_id = #{dailyUserId}
</delete>
<delete id="deleteDailyUserByDailyUserIds" parameterType="String">
delete from daily_user where daily_user_id in
<foreach item="dailyUserId" collection="array" open="(" separator="," close=")">
#{dailyUserId}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.StUserMapper">
<resultMap type="StUser" id="StUserResult">
<result property="userId" column="user_id" />
<result property="seOnlineTime" column="se_online_time" />
<result property="thOnlineTime" column="th_online_time" />
<result property="seMrTime" column="se_mr_time" />
<result property="thMrTime" column="th_mr_time" />
<result property="seConsumption" column="se_consumption" />
<result property="thConsumption" column="th_consumption" />
<result property="seWork" column="se_work" />
<result property="thWork" column="th_work" />
<result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" />
<result property="date" column="date" />
</resultMap>
<sql id="selectStUserVo">
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
</sql>
<select id="selectStUserList" parameterType="StUser" resultMap="StUserResult">
<include refid="selectStUserVo"/>
<where>
<if test="seOnlineTime != null "> and se_online_time = #{seOnlineTime}</if>
<if test="thOnlineTime != null "> and th_online_time = #{thOnlineTime}</if>
<if test="seMrTime != null "> and se_mr_time = #{seMrTime}</if>
<if test="thMrTime != null "> and th_mr_time = #{thMrTime}</if>
<if test="seConsumption != null "> and se_consumption = #{seConsumption}</if>
<if test="thConsumption != null "> and th_consumption = #{thConsumption}</if>
<if test="seWork != null "> and se_work = #{seWork}</if>
<if test="thWork != null "> and th_work = #{thWork}</if>
<if test="date != null "> and date = #{date}</if>
</where>
</select>
<select id="selectStUserByUserId" parameterType="Long" resultMap="StUserResult">
<include refid="selectStUserVo"/>
where user_id = #{userId}
</select>
<select id="getAllUserIds" resultType="java.lang.Long">
select user_id from st_user
</select>
<insert id="insertStUser" parameterType="StUser" useGeneratedKeys="true" keyProperty="userId">
insert into st_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="seOnlineTime != null">se_online_time,</if>
<if test="thOnlineTime != null">th_online_time,</if>
<if test="seMrTime != null">se_mr_time,</if>
<if test="thMrTime != null">th_mr_time,</if>
<if test="seConsumption != null">se_consumption,</if>
<if test="thConsumption != null">th_consumption,</if>
<if test="seWork != null">se_work,</if>
<if test="thWork != null">th_work,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
<if test="date != null">date,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="seOnlineTime != null">#{seOnlineTime},</if>
<if test="thOnlineTime != null">#{thOnlineTime},</if>
<if test="seMrTime != null">#{seMrTime},</if>
<if test="thMrTime != null">#{thMrTime},</if>
<if test="seConsumption != null">#{seConsumption},</if>
<if test="thConsumption != null">#{thConsumption},</if>
<if test="seWork != null">#{seWork},</if>
<if test="thWork != null">#{thWork},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="date != null">#{date},</if>
</trim>
</insert>
<update id="updateStUser" parameterType="StUser">
update st_user
<trim prefix="SET" suffixOverrides=",">
<if test="seOnlineTime != null">se_online_time = #{seOnlineTime},</if>
<if test="thOnlineTime != null">th_online_time = #{thOnlineTime},</if>
<if test="seMrTime != null">se_mr_time = #{seMrTime},</if>
<if test="thMrTime != null">th_mr_time = #{thMrTime},</if>
<if test="seConsumption != null">se_consumption = #{seConsumption},</if>
<if test="thConsumption != null">th_consumption = #{thConsumption},</if>
<if test="seWork != null">se_work = #{seWork},</if>
<if test="thWork != null">th_work = #{thWork},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="date != null">date = #{date},</if>
</trim>
where user_id = #{userId}
</update>
<delete id="deleteStUserByUserId" parameterType="Long">
delete from st_user where user_id = #{userId}
</delete>
<delete id="deleteStUserByUserIds" parameterType="String">
delete from st_user where user_id in
<foreach item="userId" collection="array" open="(" separator="," close=")">
#{userId}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.SysMessageMapper">
<resultMap type="SysMessage" id="SysMessageResult">
<result property="messageId" column="message_id" />
<result property="sendUserId" column="send_user_id" />
<result property="receiveUserId" column="receive_user_id" />
<result property="messageContent" column="message_content" />
<result property="createTime" column="create_time" />
<result property="createBy" column="create_by" />
<result property="messageType" column="message_type" />
<result property="updateTime" column="update_time" />
<result property="updateBy" column="update_by" />
<result property="messageStatus" column="message_status" />
<result property="delFlag" column="del_flag" />
</resultMap>
<sql id="selectSysMessageVo">
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
</sql>
<select id="selectSysMessageList" parameterType="SysMessage" resultMap="SysMessageResult">
<include refid="selectSysMessageVo"/>
<where>
<if test="sendUserId != null "> and send_user_id = #{sendUserId}</if>
<if test="receiveUserId != null "> and receive_user_id = #{receiveUserId}</if>
<if test="messageContent != null and messageContent != ''"> and message_content = #{messageContent}</if>
<if test="messageType != null and messageType != ''"> and message_type = #{messageType}</if>
<if test="messageStatus != null and messageStatus != ''"> and message_status = #{messageStatus}</if>
</where>
</select>
<select id="selectSysMessageByMessageId" parameterType="Long" resultMap="SysMessageResult">
<include refid="selectSysMessageVo"/>
where message_id = #{messageId}
</select>
<insert id="insertSysMessage" parameterType="SysMessage" useGeneratedKeys="true" keyProperty="messageId">
insert into sys_message
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="sendUserId != null">send_user_id,</if>
<if test="receiveUserId != null">receive_user_id,</if>
<if test="messageContent != null and messageContent != ''">message_content,</if>
<if test="createTime != null">create_time,</if>
<if test="createBy != null">create_by,</if>
<if test="messageType != null">message_type,</if>
<if test="updateTime != null">update_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="messageStatus != null">message_status,</if>
<if test="delFlag != null">del_flag,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="sendUserId != null">#{sendUserId},</if>
<if test="receiveUserId != null">#{receiveUserId},</if>
<if test="messageContent != null and messageContent != ''">#{messageContent},</if>
<if test="createTime != null">#{createTime},</if>
<if test="createBy != null">#{createBy},</if>
<if test="messageType != null">#{messageType},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="messageStatus != null">#{messageStatus},</if>
<if test="delFlag != null">#{delFlag},</if>
</trim>
</insert>
<update id="updateSysMessage" parameterType="SysMessage">
update sys_message
<trim prefix="SET" suffixOverrides=",">
<if test="sendUserId != null">send_user_id = #{sendUserId},</if>
<if test="receiveUserId != null">receive_user_id = #{receiveUserId},</if>
<if test="messageContent != null and messageContent != ''">message_content = #{messageContent},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="messageType != null">message_type = #{messageType},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="messageStatus != null">message_status = #{messageStatus},</if>
<if test="delFlag != null">del_flag = #{delFlag},</if>
</trim>
where message_id = #{messageId}
</update>
<delete id="deleteSysMessageByMessageId" parameterType="Long">
delete from sys_message where message_id = #{messageId}
</delete>
<delete id="deleteSysMessageByMessageIds" parameterType="String">
delete from sys_message where message_id in
<foreach item="messageId" collection="array" open="(" separator="," close=")">
#{messageId}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.SysMessageRecordMapper">
<resultMap type="SysMessageRecord" id="SysMessageRecordResult">
<result property="messageRecordId" column="message_record_id" />
<result property="messageId" column="message_id" />
<result property="userId" column="user_id" />
<result property="isRead" column="is_read" />
<result property="readTime" column="read_time" />
<result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectSysMessageRecordVo">
select message_record_id, message_id, user_id, is_read, read_time, create_time, update_time from sys_message_record
</sql>
<select id="selectSysMessageRecordList" parameterType="SysMessageRecord" resultMap="SysMessageRecordResult">
<include refid="selectSysMessageRecordVo"/>
<where>
<if test="messageId != null "> and message_id = #{messageId}</if>
<if test="userId != null "> and user_id = #{userId}</if>
<if test="isRead != null and isRead != ''"> and is_read = #{isRead}</if>
<if test="readTime != null "> and read_time = #{readTime}</if>
</where>
</select>
<select id="selectSysMessageRecordByMessageRecordId" parameterType="Long" resultMap="SysMessageRecordResult">
<include refid="selectSysMessageRecordVo"/>
where message_record_id = #{messageRecordId}
</select>
<insert id="insertSysMessageRecord" parameterType="SysMessageRecord" useGeneratedKeys="true" keyProperty="messageRecordId">
insert into sys_message_record
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="messageId != null">message_id,</if>
<if test="userId != null">user_id,</if>
<if test="isRead != null">is_read,</if>
<if test="readTime != null">read_time,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="messageId != null">#{messageId},</if>
<if test="userId != null">#{userId},</if>
<if test="isRead != null">#{isRead},</if>
<if test="readTime != null">#{readTime},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateSysMessageRecord" parameterType="SysMessageRecord">
update sys_message_record
<trim prefix="SET" suffixOverrides=",">
<if test="messageId != null">message_id = #{messageId},</if>
<if test="userId != null">user_id = #{userId},</if>
<if test="isRead != null">is_read = #{isRead},</if>
<if test="readTime != null">read_time = #{readTime},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where message_record_id = #{messageRecordId}
</update>
<delete id="deleteSysMessageRecordByMessageRecordId" parameterType="Long">
delete from sys_message_record where message_record_id = #{messageRecordId}
</delete>
<delete id="deleteSysMessageRecordByMessageRecordIds" parameterType="String">
delete from sys_message_record where message_record_id in
<foreach item="messageRecordId" collection="array" open="(" separator="," close=")">
#{messageRecordId}
</foreach>
</delete>
</mapper>

View File

@ -98,10 +98,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="tMrTime != null">t_mr_time,</if>
<if test="tOnlineTime != null">t_online_time,</if>
<if test="tConsumption != null">t_consumption,</if>
<if test="updateTime != null">update_time</if>
<if test="birth != null">date_of_birth</if>
<if test="backGround != null">back_ground</if>
<if test="calculationTime != null">calculation_time</if>
<if test="updateTime != null">update_time,</if>
<if test="birth != null">date_of_birth,</if>
<if test="backGround != null">back_ground,</if>
<if test="calculationTime != null">calculation_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="userId != null">#{userId},</if>