mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-03-29 00:33:24 +08:00
update 完成消息盒子功能前后端联动(已读未读在前端浏览器存储)
This commit is contained in:
@@ -12,12 +12,13 @@ import me.zhyd.oauth.request.AuthRequest;
|
|||||||
import me.zhyd.oauth.utils.AuthStateUtils;
|
import me.zhyd.oauth.utils.AuthStateUtils;
|
||||||
import org.dromara.common.core.constant.SystemConstants;
|
import org.dromara.common.core.constant.SystemConstants;
|
||||||
import org.dromara.common.core.domain.R;
|
import org.dromara.common.core.domain.R;
|
||||||
import org.dromara.common.core.domain.dto.PushPayload;
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
import org.dromara.common.core.domain.model.LoginBody;
|
import org.dromara.common.core.domain.model.LoginBody;
|
||||||
import org.dromara.common.core.domain.model.RegisterBody;
|
import org.dromara.common.core.domain.model.RegisterBody;
|
||||||
import org.dromara.common.core.domain.model.SocialLoginBody;
|
import org.dromara.common.core.domain.model.SocialLoginBody;
|
||||||
import org.dromara.common.core.enums.PushSourceEnum;
|
import org.dromara.common.core.enums.PushSourceEnum;
|
||||||
import org.dromara.common.core.enums.PushTypeEnum;
|
import org.dromara.common.core.enums.PushTypeEnum;
|
||||||
|
import org.dromara.common.core.service.MessageService;
|
||||||
import org.dromara.common.core.utils.DateUtils;
|
import org.dromara.common.core.utils.DateUtils;
|
||||||
import org.dromara.common.core.utils.MessageUtils;
|
import org.dromara.common.core.utils.MessageUtils;
|
||||||
import org.dromara.common.core.utils.StringUtils;
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
@@ -26,7 +27,6 @@ import org.dromara.common.encrypt.annotation.ApiEncrypt;
|
|||||||
import org.dromara.common.json.utils.JsonUtils;
|
import org.dromara.common.json.utils.JsonUtils;
|
||||||
import org.dromara.common.redis.annotation.RateLimiter;
|
import org.dromara.common.redis.annotation.RateLimiter;
|
||||||
import org.dromara.common.redis.enums.LimitType;
|
import org.dromara.common.redis.enums.LimitType;
|
||||||
import org.dromara.common.push.helper.PushHelper;
|
|
||||||
import org.dromara.common.satoken.utils.LoginHelper;
|
import org.dromara.common.satoken.utils.LoginHelper;
|
||||||
import org.dromara.common.social.config.properties.SocialLoginConfigProperties;
|
import org.dromara.common.social.config.properties.SocialLoginConfigProperties;
|
||||||
import org.dromara.common.social.config.properties.SocialProperties;
|
import org.dromara.common.social.config.properties.SocialProperties;
|
||||||
@@ -66,6 +66,7 @@ public class AuthController {
|
|||||||
private final ISysSocialService socialUserService;
|
private final ISysSocialService socialUserService;
|
||||||
private final ISysClientService clientService;
|
private final ISysClientService clientService;
|
||||||
private final ScheduledExecutorService scheduledExecutorService;
|
private final ScheduledExecutorService scheduledExecutorService;
|
||||||
|
private final MessageService messageService;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,9 +96,9 @@ public class AuthController {
|
|||||||
|
|
||||||
Long userId = LoginHelper.getUserId();
|
Long userId = LoginHelper.getUserId();
|
||||||
scheduledExecutorService.schedule(() -> {
|
scheduledExecutorService.schedule(() -> {
|
||||||
PushHelper.publishMessage(
|
messageService.publishMessage(
|
||||||
List.of(userId),
|
List.of(userId),
|
||||||
PushPayload.of(
|
PushPayloadDTO.of(
|
||||||
PushTypeEnum.MESSAGE,
|
PushTypeEnum.MESSAGE,
|
||||||
PushSourceEnum.BACKEND,
|
PushSourceEnum.BACKEND,
|
||||||
DateUtils.getTodayHour(new Date()) + "好,欢迎登录 RuoYi-Vue-Plus 后台管理系统",
|
DateUtils.getTodayHour(new Date()) + "好,欢迎登录 RuoYi-Vue-Plus 后台管理系统",
|
||||||
|
|||||||
@@ -14,11 +14,16 @@ import java.io.Serializable;
|
|||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class PushPayload implements Serializable {
|
public class PushPayloadDTO implements Serializable {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息记录ID
|
||||||
|
*/
|
||||||
|
private Long messageId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 消息类型
|
* 消息类型
|
||||||
*/
|
*/
|
||||||
@@ -49,8 +54,8 @@ public class PushPayload implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private Long timestamp;
|
private Long timestamp;
|
||||||
|
|
||||||
public static PushPayload of(String type, String source, String message, Object data) {
|
public static PushPayloadDTO of(String type, String source, String message, Object data) {
|
||||||
PushPayload payload = new PushPayload();
|
PushPayloadDTO payload = new PushPayloadDTO();
|
||||||
payload.setType(StringUtils.defaultIfBlank(type, PushTypeEnum.MESSAGE.getType()));
|
payload.setType(StringUtils.defaultIfBlank(type, PushTypeEnum.MESSAGE.getType()));
|
||||||
payload.setSource(StringUtils.defaultIfBlank(source, PushSourceEnum.BACKEND.getSource()));
|
payload.setSource(StringUtils.defaultIfBlank(source, PushSourceEnum.BACKEND.getSource()));
|
||||||
payload.setMessage(message);
|
payload.setMessage(message);
|
||||||
@@ -59,7 +64,7 @@ public class PushPayload implements Serializable {
|
|||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PushPayload of(PushTypeEnum type, PushSourceEnum source, String message, Object data) {
|
public static PushPayloadDTO of(PushTypeEnum type, PushSourceEnum source, String message, Object data) {
|
||||||
return of(
|
return of(
|
||||||
type == null ? null : type.getType(),
|
type == null ? null : type.getType(),
|
||||||
source == null ? null : source.getSource(),
|
source == null ? null : source.getSource(),
|
||||||
@@ -68,8 +73,8 @@ public class PushPayload implements Serializable {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PushPayload of(PushTypeEnum type, PushSourceEnum source, String message, Object data, String path) {
|
public static PushPayloadDTO of(PushTypeEnum type, PushSourceEnum source, String message, Object data, String path) {
|
||||||
PushPayload payload = of(type, source, message, data);
|
PushPayloadDTO payload = of(type, source, message, data);
|
||||||
payload.setPath(path);
|
payload.setPath(path);
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package org.dromara.common.core.service;
|
||||||
|
|
||||||
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用 消息服务
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
public interface MessageService {
|
||||||
|
|
||||||
|
void sendMessage(Long userId, String message);
|
||||||
|
|
||||||
|
void sendMessage(String message);
|
||||||
|
|
||||||
|
void sendMessage(Long userId, PushPayloadDTO payload);
|
||||||
|
|
||||||
|
void sendMessage(PushPayloadDTO payload);
|
||||||
|
|
||||||
|
void publishMessage(List<Long> userIds, PushPayloadDTO payload);
|
||||||
|
|
||||||
|
void publishAll(String message);
|
||||||
|
|
||||||
|
void publishAll(PushPayloadDTO payload);
|
||||||
|
}
|
||||||
@@ -63,7 +63,7 @@ public class SseController implements DisposableBean {
|
|||||||
// public R<Void> send(Long userId, String msg) {
|
// public R<Void> send(Long userId, String msg) {
|
||||||
// PushDTO dto = new PushDTO();
|
// PushDTO dto = new PushDTO();
|
||||||
// dto.setUserIds(List.of(userId));
|
// dto.setUserIds(List.of(userId));
|
||||||
// dto.setPayload(PushPayload.of("message", "backend", msg, null));
|
// dto.setPayload(PushPayloadDTO.of("message", "backend", msg, null));
|
||||||
// sessionManager.publishMessage(dto);
|
// sessionManager.publishMessage(dto);
|
||||||
// return R.ok();
|
// return R.ok();
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package org.dromara.common.push.core;
|
package org.dromara.common.push.core;
|
||||||
|
|
||||||
import org.dromara.common.core.domain.dto.PushPayload;
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
import org.dromara.common.push.dto.PushDTO;
|
import org.dromara.common.push.dto.PushDTO;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -14,11 +14,11 @@ public interface PushSessionManager {
|
|||||||
|
|
||||||
void subscribeMessage(Consumer<PushDTO> consumer);
|
void subscribeMessage(Consumer<PushDTO> consumer);
|
||||||
|
|
||||||
void sendMessage(Long userId, PushPayload payload);
|
void sendMessage(Long userId, PushPayloadDTO payload);
|
||||||
|
|
||||||
void sendMessage(PushPayload payload);
|
void sendMessage(PushPayloadDTO payload);
|
||||||
|
|
||||||
void publishMessage(PushDTO pushDTO);
|
void publishMessage(PushDTO pushDTO);
|
||||||
|
|
||||||
void publishAll(PushPayload payload);
|
void publishAll(PushPayloadDTO payload);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package org.dromara.common.push.core;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.common.core.domain.dto.PushPayload;
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
import org.dromara.common.push.constant.MessageConstants;
|
import org.dromara.common.push.constant.MessageConstants;
|
||||||
import org.dromara.common.push.dto.PushDTO;
|
import org.dromara.common.push.dto.PushDTO;
|
||||||
import org.dromara.common.core.utils.SpringUtils;
|
import org.dromara.common.core.utils.SpringUtils;
|
||||||
@@ -194,7 +194,7 @@ public class SseEmitterSessionManager implements PushSessionManager {
|
|||||||
* @param payload 要发送的消息体
|
* @param payload 要发送的消息体
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(Long userId, PushPayload payload) {
|
public void sendMessage(Long userId, PushPayloadDTO payload) {
|
||||||
sendMessage(userId, JsonUtils.toJsonString(payload));
|
sendMessage(userId, JsonUtils.toJsonString(payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ public class SseEmitterSessionManager implements PushSessionManager {
|
|||||||
* @param payload 要发送的消息体
|
* @param payload 要发送的消息体
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(PushPayload payload) {
|
public void sendMessage(PushPayloadDTO payload) {
|
||||||
sendMessage(JsonUtils.toJsonString(payload));
|
sendMessage(JsonUtils.toJsonString(payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +253,7 @@ public class SseEmitterSessionManager implements PushSessionManager {
|
|||||||
* @param message 要发布的消息内容
|
* @param message 要发布的消息内容
|
||||||
*/
|
*/
|
||||||
public void publishAll(String message) {
|
public void publishAll(String message) {
|
||||||
publishAll(PushPayload.of("message", "backend", message, null));
|
publishAll(PushPayloadDTO.of("message", "backend", message, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -262,7 +262,7 @@ public class SseEmitterSessionManager implements PushSessionManager {
|
|||||||
* @param payload 要发布的消息体
|
* @param payload 要发布的消息体
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void publishAll(PushPayload payload) {
|
public void publishAll(PushPayloadDTO payload) {
|
||||||
PushDTO dto = new PushDTO();
|
PushDTO dto = new PushDTO();
|
||||||
dto.setPayload(payload);
|
dto.setPayload(payload);
|
||||||
RedisUtils.publish(MessageConstants.MESSAGE_TOPIC, dto, consumer -> {
|
RedisUtils.publish(MessageConstants.MESSAGE_TOPIC, dto, consumer -> {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package org.dromara.common.push.core;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.common.core.domain.dto.PushPayload;
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
import org.dromara.common.core.utils.SpringUtils;
|
import org.dromara.common.core.utils.SpringUtils;
|
||||||
import org.dromara.common.json.utils.JsonUtils;
|
import org.dromara.common.json.utils.JsonUtils;
|
||||||
import org.dromara.common.push.dto.PushDTO;
|
import org.dromara.common.push.dto.PushDTO;
|
||||||
@@ -90,7 +90,7 @@ public class WebSocketSessionManager implements PushSessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(Long userId, PushPayload payload) {
|
public void sendMessage(Long userId, PushPayloadDTO payload) {
|
||||||
if (payload == null) {
|
if (payload == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,7 @@ public class WebSocketSessionManager implements PushSessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(PushPayload payload) {
|
public void sendMessage(PushPayloadDTO payload) {
|
||||||
USER_TOKEN_SESSIONS.keySet().forEach(userId -> sendMessage(userId, payload));
|
USER_TOKEN_SESSIONS.keySet().forEach(userId -> sendMessage(userId, payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ public class WebSocketSessionManager implements PushSessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void publishAll(PushPayload payload) {
|
public void publishAll(PushPayloadDTO payload) {
|
||||||
PushDTO dto = new PushDTO();
|
PushDTO dto = new PushDTO();
|
||||||
dto.setPayload(payload);
|
dto.setPayload(payload);
|
||||||
publishMessage(dto);
|
publishMessage(dto);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package org.dromara.common.push.dto;
|
package org.dromara.common.push.dto;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.dromara.common.core.domain.dto.PushPayload;
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -26,5 +26,5 @@ public class PushDTO implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 推送消息体。
|
* 推送消息体。
|
||||||
*/
|
*/
|
||||||
private PushPayload payload;
|
private PushPayloadDTO payload;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package org.dromara.common.push.handler;
|
|||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.common.core.domain.dto.PushPayload;
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
import org.dromara.common.core.domain.model.LoginUser;
|
import org.dromara.common.core.domain.model.LoginUser;
|
||||||
import org.dromara.common.core.enums.PushSourceEnum;
|
import org.dromara.common.core.enums.PushSourceEnum;
|
||||||
import org.dromara.common.core.enums.PushTypeEnum;
|
import org.dromara.common.core.enums.PushTypeEnum;
|
||||||
@@ -61,7 +61,7 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
|
|||||||
}
|
}
|
||||||
PushDTO dto = new PushDTO();
|
PushDTO dto = new PushDTO();
|
||||||
dto.setUserIds(List.of(loginUser.getUserId()));
|
dto.setUserIds(List.of(loginUser.getUserId()));
|
||||||
dto.setPayload(PushPayload.of(
|
dto.setPayload(PushPayloadDTO.of(
|
||||||
PushTypeEnum.CUSTOM,
|
PushTypeEnum.CUSTOM,
|
||||||
PushSourceEnum.CLIENT,
|
PushSourceEnum.CLIENT,
|
||||||
message.getPayload(),
|
message.getPayload(),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.dromara.common.push.helper;
|
|||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.dromara.common.core.domain.dto.PushPayload;
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
import org.dromara.common.core.enums.PushSourceEnum;
|
import org.dromara.common.core.enums.PushSourceEnum;
|
||||||
import org.dromara.common.core.enums.PushTypeEnum;
|
import org.dromara.common.core.enums.PushTypeEnum;
|
||||||
import org.dromara.common.core.utils.SpringUtils;
|
import org.dromara.common.core.utils.SpringUtils;
|
||||||
@@ -27,21 +27,21 @@ public class PushHelper {
|
|||||||
sendMessage(buildMessage(message));
|
sendMessage(buildMessage(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendMessage(Long userId, PushPayload payload) {
|
public static void sendMessage(Long userId, PushPayloadDTO payload) {
|
||||||
if (!isEnabled()) {
|
if (!isEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getSessionManager().sendMessage(userId, payload);
|
getSessionManager().sendMessage(userId, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendMessage(PushPayload payload) {
|
public static void sendMessage(PushPayloadDTO payload) {
|
||||||
if (!isEnabled()) {
|
if (!isEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getSessionManager().sendMessage(payload);
|
getSessionManager().sendMessage(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void publishMessage(List<Long> userIds, PushPayload payload) {
|
public static void publishMessage(List<Long> userIds, PushPayloadDTO payload) {
|
||||||
PushDTO dto = new PushDTO();
|
PushDTO dto = new PushDTO();
|
||||||
dto.setUserIds(userIds);
|
dto.setUserIds(userIds);
|
||||||
dto.setPayload(payload);
|
dto.setPayload(payload);
|
||||||
@@ -59,7 +59,7 @@ public class PushHelper {
|
|||||||
publishAll(buildMessage(message));
|
publishAll(buildMessage(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void publishAll(PushPayload payload) {
|
public static void publishAll(PushPayloadDTO payload) {
|
||||||
if (!isEnabled()) {
|
if (!isEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ public class PushHelper {
|
|||||||
return SpringUtils.getBean(PushSessionManager.class);
|
return SpringUtils.getBean(PushSessionManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PushPayload buildMessage(String message) {
|
private static PushPayloadDTO buildMessage(String message) {
|
||||||
return PushPayload.of(PushTypeEnum.MESSAGE, PushSourceEnum.BACKEND, message, null);
|
return PushPayloadDTO.of(PushTypeEnum.MESSAGE, PushSourceEnum.BACKEND, message, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package org.dromara.demo.controller;
|
package org.dromara.demo.controller;
|
||||||
|
|
||||||
import org.dromara.common.core.domain.R;
|
import org.dromara.common.core.domain.R;
|
||||||
import org.dromara.common.core.domain.dto.PushPayload;
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
import org.dromara.common.core.enums.PushSourceEnum;
|
import org.dromara.common.core.enums.PushSourceEnum;
|
||||||
import org.dromara.common.core.enums.PushTypeEnum;
|
import org.dromara.common.core.enums.PushTypeEnum;
|
||||||
import org.dromara.common.push.helper.PushHelper;
|
import org.dromara.common.core.service.MessageService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@@ -24,6 +24,8 @@ import java.util.List;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class WebSocketController {
|
public class WebSocketController {
|
||||||
|
|
||||||
|
private final MessageService messageService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发布消息
|
* 发布消息
|
||||||
*
|
*
|
||||||
@@ -32,16 +34,16 @@ public class WebSocketController {
|
|||||||
*/
|
*/
|
||||||
@GetMapping("/send")
|
@GetMapping("/send")
|
||||||
public R<Void> send(Long userId, String message) {
|
public R<Void> send(Long userId, String message) {
|
||||||
PushPayload payload = PushPayload.of(
|
PushPayloadDTO payload = PushPayloadDTO.of(
|
||||||
PushTypeEnum.MESSAGE,
|
PushTypeEnum.MESSAGE,
|
||||||
PushSourceEnum.BACKEND,
|
PushSourceEnum.BACKEND,
|
||||||
message,
|
message,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
PushHelper.publishAll(payload);
|
messageService.publishAll(payload);
|
||||||
} else {
|
} else {
|
||||||
PushHelper.publishMessage(List.of(userId), payload);
|
messageService.publishMessage(List.of(userId), payload);
|
||||||
}
|
}
|
||||||
return R.ok("操作成功");
|
return R.ok("操作成功");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package org.dromara.system.controller.system;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.dromara.common.core.domain.R;
|
||||||
|
import org.dromara.common.satoken.utils.LoginHelper;
|
||||||
|
import org.dromara.common.web.core.BaseController;
|
||||||
|
import org.dromara.system.domain.vo.SysMessageBoxVo;
|
||||||
|
import org.dromara.system.service.ISysMessageService;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息记录控制器
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/system/message")
|
||||||
|
public class SysMessageController extends BaseController {
|
||||||
|
|
||||||
|
private final ISysMessageService messageService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询当前用户消息盒子数据
|
||||||
|
*
|
||||||
|
* @return 消息盒子数据
|
||||||
|
*/
|
||||||
|
@GetMapping("/box")
|
||||||
|
public R<SysMessageBoxVo> getBox() {
|
||||||
|
return R.ok(messageService.queryMessageBox(LoginHelper.getUserId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,14 +4,14 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.dromara.common.core.domain.PageResult;
|
import org.dromara.common.core.domain.PageResult;
|
||||||
import org.dromara.common.core.domain.R;
|
import org.dromara.common.core.domain.R;
|
||||||
import org.dromara.common.core.domain.dto.PushPayload;
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
import org.dromara.common.core.enums.PushSourceEnum;
|
import org.dromara.common.core.enums.PushSourceEnum;
|
||||||
import org.dromara.common.core.enums.PushTypeEnum;
|
import org.dromara.common.core.enums.PushTypeEnum;
|
||||||
import org.dromara.common.core.service.DictService;
|
import org.dromara.common.core.service.DictService;
|
||||||
|
import org.dromara.common.core.service.MessageService;
|
||||||
import org.dromara.common.log.annotation.Log;
|
import org.dromara.common.log.annotation.Log;
|
||||||
import org.dromara.common.log.enums.BusinessType;
|
import org.dromara.common.log.enums.BusinessType;
|
||||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
import org.dromara.common.push.helper.PushHelper;
|
|
||||||
import org.dromara.common.redis.annotation.RepeatSubmit;
|
import org.dromara.common.redis.annotation.RepeatSubmit;
|
||||||
import org.dromara.common.web.core.BaseController;
|
import org.dromara.common.web.core.BaseController;
|
||||||
import org.dromara.system.domain.bo.SysNoticeBo;
|
import org.dromara.system.domain.bo.SysNoticeBo;
|
||||||
@@ -36,6 +36,7 @@ public class SysNoticeController extends BaseController {
|
|||||||
|
|
||||||
private final ISysNoticeService noticeService;
|
private final ISysNoticeService noticeService;
|
||||||
private final DictService dictService;
|
private final DictService dictService;
|
||||||
|
private final MessageService messageService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询通知公告列表。
|
* 分页查询通知公告列表。
|
||||||
@@ -83,7 +84,9 @@ public class SysNoticeController extends BaseController {
|
|||||||
data.put("noticeTypeLabel", type);
|
data.put("noticeTypeLabel", type);
|
||||||
data.put("noticeTitle", notice.getNoticeTitle());
|
data.put("noticeTitle", notice.getNoticeTitle());
|
||||||
data.put("noticeId", notice.getNoticeId());
|
data.put("noticeId", notice.getNoticeId());
|
||||||
PushHelper.publishAll(PushPayload.of(
|
data.put("noticeContent", notice.getNoticeContent());
|
||||||
|
data.put("status", notice.getStatus());
|
||||||
|
messageService.publishAll(PushPayloadDTO.of(
|
||||||
PushTypeEnum.NOTICE,
|
PushTypeEnum.NOTICE,
|
||||||
PushSourceEnum.NOTICE,
|
PushSourceEnum.NOTICE,
|
||||||
"[" + type + "] " + notice.getNoticeTitle(),
|
"[" + type + "] " + notice.getNoticeTitle(),
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package org.dromara.system.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息记录表 sys_message
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@TableName("sys_message")
|
||||||
|
public class SysMessage extends BaseEntity {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "message_id")
|
||||||
|
private Long messageId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息分组
|
||||||
|
*/
|
||||||
|
private String category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息来源
|
||||||
|
*/
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标题
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 摘要消息
|
||||||
|
*/
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 详细内容
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扩展数据 JSON
|
||||||
|
*/
|
||||||
|
private String dataJson;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端跳转路径
|
||||||
|
*/
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 目标用户ID串,0 表示全局
|
||||||
|
*/
|
||||||
|
private String sendUserIds;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package org.dromara.system.domain.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息盒子视图对象
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SysMessageBoxVo implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统消息
|
||||||
|
*/
|
||||||
|
private List<SysMessageVo> systemList = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通知公告消息
|
||||||
|
*/
|
||||||
|
private List<SysMessageVo> noticeList = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作流消息
|
||||||
|
*/
|
||||||
|
private List<SysMessageVo> workflowList = new ArrayList<>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package org.dromara.system.domain.vo;
|
||||||
|
|
||||||
|
import io.github.linpeilie.annotations.AutoMapper;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.dromara.system.domain.SysMessage;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息记录视图对象 sys_message
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AutoMapper(target = SysMessage.class)
|
||||||
|
public class SysMessageVo implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息ID
|
||||||
|
*/
|
||||||
|
private Long messageId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息分组
|
||||||
|
*/
|
||||||
|
private String category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息来源
|
||||||
|
*/
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标题
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 摘要消息
|
||||||
|
*/
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 详细内容
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扩展数据
|
||||||
|
*/
|
||||||
|
private Object data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端跳转路径
|
||||||
|
*/
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private Date createTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package org.dromara.system.mapper;
|
||||||
|
|
||||||
|
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||||
|
import org.dromara.system.domain.SysMessage;
|
||||||
|
import org.dromara.system.domain.vo.SysMessageVo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息记录Mapper接口
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
public interface SysMessageMapper extends BaseMapperPlus<SysMessage, SysMessageVo> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package org.dromara.system.service;
|
||||||
|
|
||||||
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
|
import org.dromara.system.domain.vo.SysMessageBoxVo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息记录服务接口
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
public interface ISysMessageService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询当前用户消息盒子数据
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 消息盒子数据
|
||||||
|
*/
|
||||||
|
SysMessageBoxVo queryMessageBox(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送指定用户文本消息
|
||||||
|
*
|
||||||
|
* @param userId 目标用户
|
||||||
|
* @param message 文本消息
|
||||||
|
*/
|
||||||
|
void sendMessage(Long userId, String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 广播文本消息
|
||||||
|
*
|
||||||
|
* @param message 文本消息
|
||||||
|
*/
|
||||||
|
void sendMessage(String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送指定用户消息
|
||||||
|
*
|
||||||
|
* @param userId 目标用户
|
||||||
|
* @param payload 推送消息体
|
||||||
|
*/
|
||||||
|
void sendMessage(Long userId, PushPayloadDTO payload);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 广播消息
|
||||||
|
*
|
||||||
|
* @param payload 推送消息体
|
||||||
|
*/
|
||||||
|
void sendMessage(PushPayloadDTO payload);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布指定用户消息
|
||||||
|
*
|
||||||
|
* @param userIds 用户ID列表
|
||||||
|
* @param payload 推送消息体
|
||||||
|
*/
|
||||||
|
void publishMessage(List<Long> userIds, PushPayloadDTO payload);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布广播文本消息
|
||||||
|
*
|
||||||
|
* @param message 文本消息
|
||||||
|
*/
|
||||||
|
void publishAll(String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布广播消息
|
||||||
|
*
|
||||||
|
* @param payload 推送消息体
|
||||||
|
*/
|
||||||
|
void publishAll(PushPayloadDTO payload);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录全局消息
|
||||||
|
*
|
||||||
|
* @param payload 推送消息体
|
||||||
|
* @return 回填消息ID后的推送消息体
|
||||||
|
*/
|
||||||
|
PushPayloadDTO storeAll(PushPayloadDTO payload);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录指定用户消息
|
||||||
|
*
|
||||||
|
* @param userIds 用户ID列表
|
||||||
|
* @param payload 推送消息体
|
||||||
|
* @return 回填消息ID后的推送消息体
|
||||||
|
*/
|
||||||
|
PushPayloadDTO storeUsers(List<Long> userIds, PushPayloadDTO payload);
|
||||||
|
}
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
package org.dromara.system.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.convert.Convert;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
|
import org.dromara.common.core.enums.PushSourceEnum;
|
||||||
|
import org.dromara.common.core.enums.PushTypeEnum;
|
||||||
|
import org.dromara.common.core.service.MessageService;
|
||||||
|
import org.dromara.common.core.utils.MapstructUtils;
|
||||||
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
|
import org.dromara.common.json.utils.JsonUtils;
|
||||||
|
import org.dromara.common.mybatis.helper.DataBaseHelper;
|
||||||
|
import org.dromara.common.mybatis.utils.IdGeneratorUtil;
|
||||||
|
import org.dromara.common.push.helper.PushHelper;
|
||||||
|
import org.dromara.system.domain.SysMessage;
|
||||||
|
import org.dromara.system.domain.vo.SysMessageBoxVo;
|
||||||
|
import org.dromara.system.domain.vo.SysMessageVo;
|
||||||
|
import org.dromara.system.mapper.SysMessageMapper;
|
||||||
|
import org.dromara.system.service.ISysMessageService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息记录服务实现
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Service
|
||||||
|
public class SysMessageServiceImpl implements ISysMessageService, MessageService {
|
||||||
|
|
||||||
|
private static final String GLOBAL_USER_IDS = "0";
|
||||||
|
private static final String CATEGORY_SYSTEM = "system";
|
||||||
|
private static final String CATEGORY_NOTICE = "notice";
|
||||||
|
private static final String CATEGORY_WORKFLOW = "workflow";
|
||||||
|
private static final int BOX_LIMIT = 100;
|
||||||
|
private static final long BOX_DAYS = 30L;
|
||||||
|
|
||||||
|
private final SysMessageMapper baseMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SysMessageBoxVo queryMessageBox(Long userId) {
|
||||||
|
SysMessageBoxVo box = new SysMessageBoxVo();
|
||||||
|
box.setSystemList(selectMessageList(CATEGORY_SYSTEM, userId));
|
||||||
|
box.setNoticeList(selectMessageList(CATEGORY_NOTICE, userId));
|
||||||
|
box.setWorkflowList(selectMessageList(CATEGORY_WORKFLOW, userId));
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(Long userId, String message) {
|
||||||
|
PushHelper.sendMessage(userId, buildDefaultMessage(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(String message) {
|
||||||
|
PushHelper.sendMessage(buildDefaultMessage(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(Long userId, PushPayloadDTO payload) {
|
||||||
|
PushHelper.sendMessage(userId, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(PushPayloadDTO payload) {
|
||||||
|
PushHelper.sendMessage(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publishMessage(List<Long> userIds, PushPayloadDTO payload) {
|
||||||
|
PushHelper.publishMessage(userIds, storeUsers(userIds, payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publishAll(String message) {
|
||||||
|
publishAll(buildDefaultMessage(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publishAll(PushPayloadDTO payload) {
|
||||||
|
PushHelper.publishAll(storeAll(payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PushPayloadDTO storeAll(PushPayloadDTO payload) {
|
||||||
|
return storeMessage(null, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PushPayloadDTO storeUsers(List<Long> userIds, PushPayloadDTO payload) {
|
||||||
|
return storeMessage(userIds, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PushPayloadDTO storeMessage(List<Long> userIds, PushPayloadDTO payload) {
|
||||||
|
if (!supportsMessageBox(payload)) {
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
SysMessage message = buildMessage(userIds, payload);
|
||||||
|
baseMapper.insert(message);
|
||||||
|
payload.setMessageId(message.getMessageId());
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SysMessageVo> selectMessageList(String category, Long userId) {
|
||||||
|
LambdaQueryWrapper<SysMessage> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.eq(SysMessage::getCategory, category);
|
||||||
|
lqw.ge(SysMessage::getCreateTime, new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(BOX_DAYS)));
|
||||||
|
lqw.and(wrapper -> wrapper.eq(SysMessage::getSendUserIds, GLOBAL_USER_IDS)
|
||||||
|
.or()
|
||||||
|
.apply(DataBaseHelper.findInSet(userId, "send_user_ids")));
|
||||||
|
lqw.orderByDesc(SysMessage::getCreateTime, SysMessage::getMessageId);
|
||||||
|
List<SysMessage> list = baseMapper.selectList(new Page<>(1, BOX_LIMIT, false), lqw);
|
||||||
|
return list.stream().map(this::buildVo).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SysMessage buildMessage(List<Long> userIds, PushPayloadDTO payload) {
|
||||||
|
SysMessage message = new SysMessage();
|
||||||
|
message.setMessageId(payload.getMessageId() == null ? IdGeneratorUtil.nextLongId() : payload.getMessageId());
|
||||||
|
message.setCategory(resolveCategory(payload));
|
||||||
|
message.setType(payload.getType());
|
||||||
|
message.setSource(payload.getSource());
|
||||||
|
message.setTitle(resolveTitle(payload));
|
||||||
|
message.setMessage(payload.getMessage());
|
||||||
|
message.setContent(resolveContent(payload));
|
||||||
|
message.setDataJson(JsonUtils.toJsonString(payload.getData()));
|
||||||
|
message.setPath(payload.getPath());
|
||||||
|
message.setSendUserIds(CollUtil.isEmpty(userIds) ? GLOBAL_USER_IDS : StringUtils.joinComma(userIds));
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SysMessageVo buildVo(SysMessage entity) {
|
||||||
|
SysMessageVo vo = MapstructUtils.convert(entity, SysMessageVo.class);
|
||||||
|
vo.setData(parseData(entity.getDataJson()));
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean supportsMessageBox(PushPayloadDTO payload) {
|
||||||
|
if (payload == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (StringUtils.equalsAny(payload.getType(), PushTypeEnum.MESSAGE.getType(), PushTypeEnum.NOTICE.getType())) {
|
||||||
|
return !StringUtils.equalsAny(payload.getType(), PushTypeEnum.LLM.getType())
|
||||||
|
&& !StringUtils.equalsAny(payload.getSource(), PushSourceEnum.LLM.getSource());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveCategory(PushPayloadDTO payload) {
|
||||||
|
if (StringUtils.equalsAny(payload.getType(), PushTypeEnum.NOTICE.getType())
|
||||||
|
|| StringUtils.equalsAny(payload.getSource(), PushSourceEnum.NOTICE.getSource())) {
|
||||||
|
return CATEGORY_NOTICE;
|
||||||
|
}
|
||||||
|
if (StringUtils.equalsAny(payload.getSource(), PushSourceEnum.WORKFLOW.getSource())) {
|
||||||
|
return CATEGORY_WORKFLOW;
|
||||||
|
}
|
||||||
|
return CATEGORY_SYSTEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveTitle(PushPayloadDTO payload) {
|
||||||
|
return switch (resolveCategory(payload)) {
|
||||||
|
case CATEGORY_NOTICE -> "通知公告消息";
|
||||||
|
case CATEGORY_WORKFLOW -> "工作流消息";
|
||||||
|
default -> "系统消息";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveContent(PushPayloadDTO payload) {
|
||||||
|
Object data = payload.getData();
|
||||||
|
if (data instanceof Map<?, ?> map) {
|
||||||
|
return Convert.toStr(map.get("noticeContent"));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object parseData(String dataJson) {
|
||||||
|
if (StringUtils.isBlank(dataJson)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return JsonUtils.parseObject(dataJson, Object.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PushPayloadDTO buildDefaultMessage(String message) {
|
||||||
|
return PushPayloadDTO.of(PushTypeEnum.MESSAGE, PushSourceEnum.BACKEND, message, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?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="org.dromara.system.mapper.SysMessageMapper">
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -4,16 +4,16 @@ import cn.hutool.core.collection.CollUtil;
|
|||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.common.core.domain.dto.PushPayload;
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
import org.dromara.common.core.domain.dto.UserDTO;
|
import org.dromara.common.core.domain.dto.UserDTO;
|
||||||
import org.dromara.common.core.enums.PushSourceEnum;
|
import org.dromara.common.core.enums.PushSourceEnum;
|
||||||
import org.dromara.common.core.enums.PushTypeEnum;
|
import org.dromara.common.core.enums.PushTypeEnum;
|
||||||
import org.dromara.common.core.exception.ServiceException;
|
import org.dromara.common.core.exception.ServiceException;
|
||||||
|
import org.dromara.common.core.service.MessageService;
|
||||||
import org.dromara.common.core.utils.SpringUtils;
|
import org.dromara.common.core.utils.SpringUtils;
|
||||||
import org.dromara.common.core.utils.StreamUtils;
|
import org.dromara.common.core.utils.StreamUtils;
|
||||||
import org.dromara.common.core.utils.StringUtils;
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
import org.dromara.common.mail.utils.MailUtils;
|
import org.dromara.common.mail.utils.MailUtils;
|
||||||
import org.dromara.common.push.helper.PushHelper;
|
|
||||||
import org.dromara.warm.flow.core.FlowEngine;
|
import org.dromara.warm.flow.core.FlowEngine;
|
||||||
import org.dromara.warm.flow.core.entity.Node;
|
import org.dromara.warm.flow.core.entity.Node;
|
||||||
import org.dromara.warm.flow.orm.entity.FlowTask;
|
import org.dromara.warm.flow.orm.entity.FlowTask;
|
||||||
@@ -41,6 +41,7 @@ import java.util.Set;
|
|||||||
public class FlwCommonServiceImpl implements IFlwCommonService {
|
public class FlwCommonServiceImpl implements IFlwCommonService {
|
||||||
|
|
||||||
private static final String DEFAULT_SUBJECT = "单据审批提醒";
|
private static final String DEFAULT_SUBJECT = "单据审批提醒";
|
||||||
|
private final MessageService messageService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据流程实例发送消息给当前处理人
|
* 根据流程实例发送消息给当前处理人
|
||||||
@@ -94,7 +95,7 @@ public class FlwCommonServiceImpl implements IFlwCommonService {
|
|||||||
try {
|
try {
|
||||||
switch (messageTypeEnum) {
|
switch (messageTypeEnum) {
|
||||||
case SYSTEM_MESSAGE -> {
|
case SYSTEM_MESSAGE -> {
|
||||||
PushHelper.publishMessage(userIds, PushPayload.of(
|
messageService.publishMessage(userIds, PushPayloadDTO.of(
|
||||||
PushTypeEnum.MESSAGE,
|
PushTypeEnum.MESSAGE,
|
||||||
PushSourceEnum.WORKFLOW,
|
PushSourceEnum.WORKFLOW,
|
||||||
message,
|
message,
|
||||||
|
|||||||
@@ -925,7 +925,50 @@ insert into sys_notice values('2', '维护通知:2018-07-01 系统凌晨维护
|
|||||||
|
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- 18、代码生成业务表
|
-- 18、消息记录表
|
||||||
|
-- ----------------------------
|
||||||
|
create table sys_message (
|
||||||
|
message_id number(20) not null,
|
||||||
|
category varchar2(20) not null,
|
||||||
|
type varchar2(20) not null,
|
||||||
|
source varchar2(20) not null,
|
||||||
|
title varchar2(100) default '',
|
||||||
|
message varchar2(500) default '',
|
||||||
|
content clob default null,
|
||||||
|
data_json clob default null,
|
||||||
|
path varchar2(500) default null,
|
||||||
|
send_user_ids varchar2(2000) default '0' not null,
|
||||||
|
create_dept number(20) default null,
|
||||||
|
create_by number(20) default null,
|
||||||
|
create_time date,
|
||||||
|
update_by number(20) default null,
|
||||||
|
update_time date
|
||||||
|
);
|
||||||
|
|
||||||
|
alter table sys_message add constraint pk_sys_message primary key (message_id);
|
||||||
|
|
||||||
|
create index idx_sys_message_category_time on sys_message(category, create_time);
|
||||||
|
|
||||||
|
comment on table sys_message is '消息记录表';
|
||||||
|
comment on column sys_message.message_id is '消息ID';
|
||||||
|
comment on column sys_message.category is '消息分组(system/notice/workflow)';
|
||||||
|
comment on column sys_message.type is '消息类型';
|
||||||
|
comment on column sys_message.source is '消息来源';
|
||||||
|
comment on column sys_message.title is '标题';
|
||||||
|
comment on column sys_message.message is '摘要消息';
|
||||||
|
comment on column sys_message.content is '详细内容';
|
||||||
|
comment on column sys_message.data_json is '扩展数据JSON';
|
||||||
|
comment on column sys_message.path is '前端跳转路径';
|
||||||
|
comment on column sys_message.send_user_ids is '目标用户ID串,0表示全局';
|
||||||
|
comment on column sys_message.create_dept is '创建部门';
|
||||||
|
comment on column sys_message.create_by is '创建者';
|
||||||
|
comment on column sys_message.create_time is '创建时间';
|
||||||
|
comment on column sys_message.update_by is '更新者';
|
||||||
|
comment on column sys_message.update_time is '更新时间';
|
||||||
|
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- 19、代码生成业务表
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
create table gen_table (
|
create table gen_table (
|
||||||
table_id number(20) not null,
|
table_id number(20) not null,
|
||||||
@@ -980,7 +1023,7 @@ comment on column gen_table.remark is '备注';
|
|||||||
|
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- 19、代码生成业务表字段
|
-- 20、代码生成业务表字段
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
create table gen_table_column (
|
create table gen_table_column (
|
||||||
column_id number(20) not null,
|
column_id number(20) not null,
|
||||||
|
|||||||
@@ -923,7 +923,50 @@ insert into sys_notice values('2', '维护通知:2018-07-01 系统凌晨维护
|
|||||||
|
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- 18、代码生成业务表
|
-- 18、消息记录表
|
||||||
|
-- ----------------------------
|
||||||
|
create table if not exists sys_message
|
||||||
|
(
|
||||||
|
message_id int8,
|
||||||
|
category varchar(20) not null,
|
||||||
|
type varchar(20) not null,
|
||||||
|
source varchar(20) not null,
|
||||||
|
title varchar(100) default ''::varchar,
|
||||||
|
message varchar(500) default ''::varchar,
|
||||||
|
content text,
|
||||||
|
data_json text,
|
||||||
|
path varchar(500) default null::varchar,
|
||||||
|
send_user_ids varchar(2000) not null default '0'::varchar,
|
||||||
|
create_dept int8,
|
||||||
|
create_by int8,
|
||||||
|
create_time timestamp,
|
||||||
|
update_by int8,
|
||||||
|
update_time timestamp,
|
||||||
|
constraint sys_message_pk primary key (message_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
create index if not exists idx_sys_message_category_time on sys_message (category, create_time);
|
||||||
|
|
||||||
|
comment on table sys_message is '消息记录表';
|
||||||
|
comment on column sys_message.message_id is '消息ID';
|
||||||
|
comment on column sys_message.category is '消息分组(system/notice/workflow)';
|
||||||
|
comment on column sys_message.type is '消息类型';
|
||||||
|
comment on column sys_message.source is '消息来源';
|
||||||
|
comment on column sys_message.title is '标题';
|
||||||
|
comment on column sys_message.message is '摘要消息';
|
||||||
|
comment on column sys_message.content is '详细内容';
|
||||||
|
comment on column sys_message.data_json is '扩展数据JSON';
|
||||||
|
comment on column sys_message.path is '前端跳转路径';
|
||||||
|
comment on column sys_message.send_user_ids is '目标用户ID串,0表示全局';
|
||||||
|
comment on column sys_message.create_dept is '创建部门';
|
||||||
|
comment on column sys_message.create_by is '创建者';
|
||||||
|
comment on column sys_message.create_time is '创建时间';
|
||||||
|
comment on column sys_message.update_by is '更新者';
|
||||||
|
comment on column sys_message.update_time is '更新时间';
|
||||||
|
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- 19、代码生成业务表
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
create table if not exists gen_table
|
create table if not exists gen_table
|
||||||
(
|
(
|
||||||
@@ -977,7 +1020,7 @@ comment on column gen_table.update_time is '更新时间';
|
|||||||
comment on column gen_table.remark is '备注';
|
comment on column gen_table.remark is '备注';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- 19、代码生成业务表字段
|
-- 20、代码生成业务表字段
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
create table if not exists gen_table_column
|
create table if not exists gen_table_column
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -689,7 +689,31 @@ insert into sys_notice values('2', '维护通知:2018-07-01 系统凌晨维护
|
|||||||
|
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- 18、代码生成业务表
|
-- 18、消息记录表
|
||||||
|
-- ----------------------------
|
||||||
|
create table sys_message (
|
||||||
|
message_id bigint(20) not null comment '消息ID',
|
||||||
|
category varchar(20) not null comment '消息分组(system/notice/workflow)',
|
||||||
|
type varchar(20) not null comment '消息类型',
|
||||||
|
source varchar(20) not null comment '消息来源',
|
||||||
|
title varchar(100) default '' comment '标题',
|
||||||
|
message varchar(500) default '' comment '摘要消息',
|
||||||
|
content longtext comment '详细内容',
|
||||||
|
data_json longtext comment '扩展数据JSON',
|
||||||
|
path varchar(500) default null comment '前端跳转路径',
|
||||||
|
send_user_ids varchar(2000) not null default '0' comment '目标用户ID串,0表示全局',
|
||||||
|
create_dept bigint(20) default null comment '创建部门',
|
||||||
|
create_by bigint(20) default null comment '创建者',
|
||||||
|
create_time datetime comment '创建时间',
|
||||||
|
update_by bigint(20) default null comment '更新者',
|
||||||
|
update_time datetime comment '更新时间',
|
||||||
|
primary key (message_id),
|
||||||
|
key idx_sys_message_category_time (category, create_time)
|
||||||
|
) engine=innodb comment = '消息记录表';
|
||||||
|
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- 19、代码生成业务表
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
create table gen_table (
|
create table gen_table (
|
||||||
table_id bigint(20) not null comment '编号',
|
table_id bigint(20) not null comment '编号',
|
||||||
|
|||||||
@@ -1674,6 +1674,130 @@ GO
|
|||||||
INSERT sys_notice VALUES (2, N'维护通知:2018-07-01 若依系统凌晨维护', N'1', N'维护内容', N'0', 103, 1, getdate(), NULL, NULL, N'管理员')
|
INSERT sys_notice VALUES (2, N'维护通知:2018-07-01 若依系统凌晨维护', N'1', N'维护内容', N'0', 103, 1, getdate(), NULL, NULL, N'管理员')
|
||||||
GO
|
GO
|
||||||
|
|
||||||
|
CREATE TABLE sys_message
|
||||||
|
(
|
||||||
|
message_id bigint NOT NULL,
|
||||||
|
category nvarchar(20) NOT NULL,
|
||||||
|
type nvarchar(20) NOT NULL,
|
||||||
|
source nvarchar(20) NOT NULL,
|
||||||
|
title nvarchar(100) DEFAULT ('') NULL,
|
||||||
|
message nvarchar(500) DEFAULT ('') NULL,
|
||||||
|
content nvarchar(max) NULL,
|
||||||
|
data_json nvarchar(max) NULL,
|
||||||
|
path nvarchar(500) NULL,
|
||||||
|
send_user_ids nvarchar(2000) DEFAULT ('0') NOT NULL,
|
||||||
|
create_dept bigint NULL,
|
||||||
|
create_by bigint NULL,
|
||||||
|
create_time datetime2(7) NULL,
|
||||||
|
update_by bigint NULL,
|
||||||
|
update_time datetime2(7) NULL,
|
||||||
|
CONSTRAINT PK__sys_mess__0BBF6EE69F35486A PRIMARY KEY CLUSTERED (message_id)
|
||||||
|
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
|
||||||
|
ON [PRIMARY]
|
||||||
|
)
|
||||||
|
ON [PRIMARY]
|
||||||
|
TEXTIMAGE_ON [PRIMARY]
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE NONCLUSTERED INDEX idx_sys_message_category_time ON sys_message(category, create_time)
|
||||||
|
GO
|
||||||
|
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'消息ID' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'message_id'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'消息分组(system/notice/workflow)' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'category'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'消息类型' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'type'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'消息来源' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'source'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'标题' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'title'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'摘要消息' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'message'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'详细内容' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'content'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'扩展数据JSON' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'data_json'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'前端跳转路径' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'path'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'目标用户ID串,0表示全局' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'send_user_ids'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'创建部门' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'create_dept'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'创建者' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'create_by'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'创建时间' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'create_time'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'更新者' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'update_by'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'更新时间' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message',
|
||||||
|
'COLUMN', N'update_time'
|
||||||
|
GO
|
||||||
|
EXEC sys.sp_addextendedproperty
|
||||||
|
'MS_Description', N'消息记录表' ,
|
||||||
|
'SCHEMA', N'dbo',
|
||||||
|
'TABLE', N'sys_message'
|
||||||
|
GO
|
||||||
|
|
||||||
CREATE TABLE sys_oper_log
|
CREATE TABLE sys_oper_log
|
||||||
(
|
(
|
||||||
oper_id bigint NOT NULL,
|
oper_id bigint NOT NULL,
|
||||||
|
|||||||
Reference in New Issue
Block a user