[fix]修改bug
This commit is contained in:
parent
b450526775
commit
c21d61f4f0
13
pom.xml
13
pom.xml
@ -102,13 +102,6 @@
|
||||
<!-- 依赖声明 -->
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
<!-- knife4j 接口文档工具 -->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||
<version>2.0.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-springdoc-ui</artifactId>
|
||||
@ -411,7 +404,11 @@
|
||||
<artifactId>ruoyi-goods</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-rabbitmq</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
|
@ -79,7 +79,7 @@ public class AppMemberController {
|
||||
if (loginUser == null) {
|
||||
throw new ServiceException("用户未登录");
|
||||
}
|
||||
return R.ok(convert.toVO(service.getById(loginUser.getUserId())));
|
||||
return R.ok(service.getMemberInfo(loginUser.getUserId()));
|
||||
}
|
||||
|
||||
@Tag(name = "获取会员账户表详细信息")
|
||||
|
@ -65,7 +65,7 @@ public class AppOrderController {
|
||||
|
||||
if (result != null) {
|
||||
// 订单创建成功,发送消息
|
||||
orderService.sendMessage(order);
|
||||
// orderService.sendMessage(order);
|
||||
log.info("订单创建成功,消息已发送,订单ID: {}", order.getId());
|
||||
} else {
|
||||
log.warn("订单创建失败: {}", "返回结果为null");
|
||||
|
@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.wzj.soopin.content.domain.bo.*;
|
||||
import com.wzj.soopin.content.domain.po.MyLikedVlog;
|
||||
import com.wzj.soopin.content.domain.po.Vlog;
|
||||
import com.wzj.soopin.content.domain.vo.IndexVlogVO;
|
||||
import com.wzj.soopin.content.service.VlogService;
|
||||
import com.wzj.soopin.content.service.VlogUploadService;
|
||||
@ -45,6 +46,16 @@ public class AppVlogController {
|
||||
@Tag(name = "首页视频列表")
|
||||
@PostMapping("/indexList")
|
||||
public R<Page<IndexVlogVO>> indexList(@RequestBody IndexListBO bo, @RequestBody Page page) {
|
||||
|
||||
try{
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
if (loginUser == null) {
|
||||
throw new ServiceException("用户未登录");
|
||||
}
|
||||
bo.setUserId(String.valueOf(loginUser.getUserId()));
|
||||
}catch (Exception e){
|
||||
log.error("用户没登陆", e);
|
||||
}
|
||||
Page<IndexVlogVO> pages = vlogService.getIndexVlogList(bo, page);
|
||||
return R.ok(pages);
|
||||
}
|
||||
@ -100,6 +111,15 @@ public class AppVlogController {
|
||||
}
|
||||
@PostMapping("publish")
|
||||
public R<Void> publish(@RequestBody VlogBO vlogBO) throws Exception {
|
||||
|
||||
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
if (loginUser == null) {
|
||||
throw new ServiceException("用户未登录");
|
||||
}
|
||||
vlogBO.setVlogerId(String.valueOf(loginUser.getUserId()));
|
||||
|
||||
|
||||
String url = vlogBO.getUrl();
|
||||
log.info("未审核视频地址:"+url);
|
||||
String fileName = url.substring(url.lastIndexOf("/") + 1);
|
||||
@ -137,18 +157,20 @@ public class AppVlogController {
|
||||
}
|
||||
|
||||
String userId = String.valueOf(loginUser.getUserId());
|
||||
String vlogerId = params.get("vlogerId");
|
||||
String vlogId = params.get("vlogId");
|
||||
|
||||
if (StringUtils.isBlank(vlogerId) || StringUtils.isBlank(vlogId)) {
|
||||
throw new ServiceException("参数不完整");
|
||||
}
|
||||
|
||||
|
||||
//获取vlog
|
||||
Vlog vlog = vlogService.getVlog(vlogId);
|
||||
if(vlog==null){
|
||||
throw new ServiceException("视频不存在");
|
||||
}
|
||||
// 我点赞的视频,关联关系保存到数据库
|
||||
vlogService.userLikeVlog(userId, vlogId);
|
||||
|
||||
// 点赞后,视频和视频发布者的获赞都会 +1
|
||||
redis.increment(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + vlogerId, 1);
|
||||
redis.increment(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + vlog.getMemberId(), 1);
|
||||
redis.increment(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
|
||||
|
||||
// 我点赞的视频,需要在redis中保存关联关系
|
||||
@ -179,17 +201,18 @@ public class AppVlogController {
|
||||
}
|
||||
|
||||
String userId = String.valueOf(loginUser.getUserId());
|
||||
String vlogerId = params.get("vlogerId");
|
||||
String vlogId = params.get("vlogId");
|
||||
|
||||
if (StringUtils.isBlank(vlogerId) || StringUtils.isBlank(vlogId)) {
|
||||
throw new ServiceException("参数不完整");
|
||||
//获取vlog
|
||||
Vlog vlog = vlogService.getVlog(vlogId);
|
||||
if(vlog==null){
|
||||
throw new ServiceException("视频不存在");
|
||||
}
|
||||
|
||||
// 我取消点赞的视频,关联关系删除
|
||||
vlogService.userUnLikeVlog(userId, vlogId);
|
||||
|
||||
redis.decrement(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + vlogerId, 1);
|
||||
redis.decrement(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + vlog.getMemberId(), 1);
|
||||
redis.decrement(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
|
||||
redis.del(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId);
|
||||
|
||||
|
@ -74,18 +74,26 @@ public class IndexServiceImpl implements IndexService {
|
||||
private void addCompositeStatistics(Map<String, Object> result) {
|
||||
// 商品统计
|
||||
Map<String, Object> productCounts = productMapper.countProduct();
|
||||
result.put("productCount", productCounts.get("count2"));
|
||||
result.put("productAudit", productCounts.get("count1"));
|
||||
if(productCounts!=null){
|
||||
result.put("productCount", productCounts.get("count2"));
|
||||
result.put("productAudit", productCounts.get("count1"));
|
||||
}
|
||||
|
||||
|
||||
// 店铺统计
|
||||
Map<String, Object> storeCounts = sysTenantMapper.countProduct();
|
||||
result.put("storeCount", storeCounts.get("count1"));
|
||||
result.put("StoreAudit", storeCounts.get("count2"));
|
||||
if(storeCounts!=null){
|
||||
result.put("storeCount", storeCounts.get("count1"));
|
||||
result.put("StoreAudit", storeCounts.get("count2"));
|
||||
}
|
||||
|
||||
// 订单统计
|
||||
Map<String, Object> orderCounts = orderMapper.countOrder();
|
||||
result.put("orderCount", orderCounts.get("count1"));
|
||||
result.put("orderAudit", orderCounts.get("count2"));
|
||||
if(orderCounts!=null){
|
||||
result.put("orderCount", orderCounts.get("count1"));
|
||||
result.put("orderAudit", orderCounts.get("count2"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Top20排行榜 */
|
||||
|
@ -31,4 +31,9 @@ public interface GlobalConstants {
|
||||
* 三方认证 redis key
|
||||
*/
|
||||
String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:";
|
||||
|
||||
/**
|
||||
* 会员 redis key
|
||||
*/
|
||||
String MEMBER_KEY = GLOBAL_REDIS_KEY + "member:";
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-common-rabbitmq</artifactId>
|
||||
|
||||
<description>
|
||||
ruoyi-common-rabbitmq
|
||||
</description>
|
||||
@ -28,6 +27,13 @@
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson for JSON -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -0,0 +1,55 @@
|
||||
package org.dromara.common.rabbitmq.config.properties;
|
||||
|
||||
|
||||
import org.springframework.amqp.core.*;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class RabbitMQConfig {
|
||||
|
||||
public static final String DIRECT_EXCHANGE_NAME = "ruoyi.direct.exchange";
|
||||
public static final String DIRECT_QUEUE_NAME = "ruoyi.direct.queue";
|
||||
public static final String DIRECT_ROUTING_KEY = "ruoyi.direct.routingkey";
|
||||
|
||||
public static final String TOPIC_EXCHANGE_NAME = "ruoyi.topic.exchange";
|
||||
public static final String TOPIC_QUEUE_NAME = "ruoyi.topic.queue";
|
||||
public static final String TOPIC_ROUTING_KEY = "ruoyi.topic.#";
|
||||
|
||||
@Bean
|
||||
public DirectExchange directExchange() {
|
||||
return new DirectExchange(DIRECT_EXCHANGE_NAME, true, false);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TopicExchange topicExchange() {
|
||||
return new TopicExchange(TOPIC_EXCHANGE_NAME, true, false);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Queue directQueue() {
|
||||
return new Queue(DIRECT_QUEUE_NAME, true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Queue topicQueue() {
|
||||
return new Queue(TOPIC_QUEUE_NAME, true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding directBinding(Queue directQueue, DirectExchange directExchange) {
|
||||
return BindingBuilder.bind(directQueue).to(directExchange).with(DIRECT_ROUTING_KEY);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding topicBinding(Queue topicQueue, TopicExchange topicExchange) {
|
||||
return BindingBuilder.bind(topicQueue).to(topicExchange).with(TOPIC_ROUTING_KEY);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageConverter jsonMessageConverter() {
|
||||
return new Jackson2JsonMessageConverter();
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package org.dromara.common.rabbitmq.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class BaseMessage {
|
||||
private String messageId;
|
||||
private String messageType;
|
||||
private Object data;
|
||||
private LocalDateTime time;
|
||||
private String source;
|
||||
|
||||
public BaseMessage() {
|
||||
this.time = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public BaseMessage(String messageType, Object data) {
|
||||
this();
|
||||
this.messageType = messageType;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
package org.dromara.common.rabbitmq.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.json.utils.JsonUtils;
|
||||
import org.dromara.common.rabbitmq.config.properties.RabbitMQConfig;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.amqp.AmqpException;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageBuilder;
|
||||
import org.springframework.amqp.core.MessageDeliveryMode;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
@Slf4j
|
||||
@Component
|
||||
public class MqUtil implements ApplicationContextAware {
|
||||
private static RabbitTemplate rabbitTemplate;
|
||||
private static MessageConverter messageConverter;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
|
||||
messageConverter = applicationContext.getBean(MessageConverter.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息到指定交换机和路由键
|
||||
*/
|
||||
public static void sendMessage(String exchange, String routingKey, Object message) {
|
||||
try {
|
||||
rabbitTemplate.convertAndSend(exchange, routingKey, message);
|
||||
log.debug("消息发送成功 - exchange: {}, routingKey: {}, message: {}", exchange, routingKey, message);
|
||||
} catch (AmqpException e) {
|
||||
log.error("消息发送失败 - exchange: {}, routingKey: {}, message: {}", exchange, routingKey, message, e);
|
||||
throw new RuntimeException("消息发送失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息到指定队列(使用默认交换机)
|
||||
*/
|
||||
public static void sendToQueue(String queueName, Object message) {
|
||||
sendMessage("", queueName, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送延迟消息
|
||||
*/
|
||||
public static void sendDelayedMessage(String exchange, String routingKey, Object message, long delayMillis) {
|
||||
try {
|
||||
Message amqpMessage = messageConverter.toMessage(message, new MessageProperties());
|
||||
amqpMessage.getMessageProperties().setDelayLong(delayMillis);
|
||||
amqpMessage.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
|
||||
|
||||
rabbitTemplate.convertAndSend(exchange, routingKey, amqpMessage);
|
||||
log.debug("延迟消息发送成功 - exchange: {}, routingKey: {}, delay: {}ms", exchange, routingKey, delayMillis);
|
||||
} catch (AmqpException e) {
|
||||
log.error("延迟消息发送失败", e);
|
||||
throw new RuntimeException("延迟消息发送失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 发送带有headers的消息
|
||||
// */
|
||||
// public static void sendMessageWithHeaders(String exchange, String routingKey, Object message, Map<String, Object> headers) {
|
||||
// try {
|
||||
// Message amqpMessage = messageConverter.toMessage(message, new MessageProperties());
|
||||
// if (headers != null) {
|
||||
// headers.forEach((key, value) -> amqpMessage.getMessageProperties().setHeader(key, value));
|
||||
// }
|
||||
//
|
||||
// rabbitTemplate.convertAndSend(exchange, routingKey, amqpMessage);
|
||||
// log.debug("带headers的消息发送成功 - exchange: {}, routingKey: {}", exchange, routingKey);
|
||||
// } catch (AmqpException e) {
|
||||
// log.error("带headers的消息发送失败", e);
|
||||
// throw new RuntimeException("消息发送失败", e);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 发送JSON格式的消息
|
||||
*/
|
||||
public static void sendJsonMessage(String exchange, String routingKey, Object message) {
|
||||
try {
|
||||
Message amqpMessage = MessageBuilder.withBody(JsonUtils.toJsonString(message).getBytes())
|
||||
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
|
||||
.setDeliveryMode(MessageDeliveryMode.PERSISTENT)
|
||||
.build();
|
||||
|
||||
rabbitTemplate.convertAndSend(exchange, routingKey, amqpMessage);
|
||||
log.debug("JSON消息发送成功 - exchange: {}, routingKey: {}", exchange, routingKey);
|
||||
} catch (AmqpException e) {
|
||||
log.error("JSON消息发送失败", e);
|
||||
throw new RuntimeException("JSON消息发送失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息并等待确认(同步方式)
|
||||
*/
|
||||
public static boolean sendMessageWithConfirm(String exchange, String routingKey, Object message) {
|
||||
try {
|
||||
rabbitTemplate.invoke(operations -> {
|
||||
operations.convertAndSend(exchange, routingKey, message);
|
||||
// 等待确认
|
||||
return operations.waitForConfirms(5000);
|
||||
});
|
||||
log.debug("消息发送并确认成功 - exchange: {}, routingKey: {}", exchange, routingKey);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error("消息发送确认失败", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息到预定义的直连交换机
|
||||
*/
|
||||
public static void sendToDirectExchange(Object message) {
|
||||
sendMessage("ruoyi.direct.exchange", "ruoyi.direct.routingkey", message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息到预定义的主题交换机
|
||||
*/
|
||||
public static void sendToTopicExchange(String routingKey, Object message) {
|
||||
sendMessage("ruoyi.topic.exchange", routingKey, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查RabbitMQ连接状态
|
||||
*/
|
||||
public static boolean isConnected() {
|
||||
try {
|
||||
rabbitTemplate.execute(channel -> {
|
||||
// 简单的连接检查
|
||||
return channel.isOpen();
|
||||
});
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.warn("RabbitMQ连接检查失败", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.dromara.common.redis.config.properties;
|
||||
package org.dromara.common.rabbitmq.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
@ -10,7 +10,7 @@ import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.redis.config.properties.RedissonProperties;
|
||||
import org.dromara.common.rabbitmq.config.properties.RedissonProperties;
|
||||
import org.dromara.common.redis.handler.KeyPrefixHandler;
|
||||
import org.dromara.common.redis.handler.RedisExceptionHandler;
|
||||
import org.redisson.client.codec.StringCodec;
|
||||
|
@ -96,6 +96,7 @@ public class PlusSpringCacheManager implements CacheManager {
|
||||
if (names != null) {
|
||||
for (String name : names) {
|
||||
getCache(name);
|
||||
|
||||
}
|
||||
dynamic = false;
|
||||
} else {
|
||||
|
@ -5,7 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
||||
import org.dromara.common.core.utils.reflect.ReflectUtils;
|
||||
import org.dromara.common.redis.config.RedisConfig;
|
||||
import org.dromara.common.redis.config.properties.RedissonProperties;
|
||||
import org.dromara.common.rabbitmq.config.properties.RedissonProperties;
|
||||
import org.dromara.common.tenant.core.TenantSaTokenDao;
|
||||
import org.dromara.common.tenant.handle.PlusTenantLineHandler;
|
||||
import org.dromara.common.tenant.handle.TenantKeyPrefixHandler;
|
||||
|
@ -144,12 +144,7 @@
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-member</artifactId>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.github.pagehelper</groupId>-->
|
||||
<!-- <artifactId>pagehelper</artifactId>-->
|
||||
<!-- <version>5.3.2</version>-->
|
||||
<!-- <scope>compile</scope>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
@ -161,12 +156,7 @@
|
||||
<artifactId>spring-rabbit</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 腾讯云视频点播SDK -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.tencentcloudapi</groupId>-->
|
||||
<!-- <artifactId>tencentcloud-sdk-java-vod</artifactId>-->
|
||||
<!-- <version>3.1.1030</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
|
||||
<!-- 腾讯云SDK公共模块 -->
|
||||
<dependency>
|
||||
@ -178,10 +168,7 @@
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-im</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 腾讯云SDK核心模块 -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.tencentcloudapi</groupId>-->
|
||||
|
@ -44,6 +44,10 @@ public class BaseInfoProperties {
|
||||
// 举报视频
|
||||
public static final String REDIS_VIDEO_BLOCK = "redis_video_block";
|
||||
|
||||
//已读视频
|
||||
public static final String REDIS_USER_READ_VLOG = "redis_user_read_vlog";
|
||||
// 已读评论
|
||||
public static final String REDIS_USER_READ_COMMENT = "redis_user_read_comment";
|
||||
|
||||
// 用户是否喜欢/点赞视频,取代数据库的关联关系,1:喜欢,0:不喜欢(默认) redis_user_like_vlog:{userId}:{vlogId}
|
||||
public static final String REDIS_USER_LIKE_VLOG = "redis_user_like_vlog";
|
||||
|
@ -206,6 +206,7 @@ public class CommentServiceImpl extends BaseInfoProperties implements CommentSer
|
||||
wrapper.eq(Comment::getVlogId, bo.getVlogId());
|
||||
}
|
||||
|
||||
wrapper.orderByDesc(Comment::getCreateTime);
|
||||
Page<Comment> commentPage = commentMapper.selectPage(page, wrapper);
|
||||
|
||||
// 转VO并加子评论数
|
||||
|
@ -19,6 +19,7 @@ import com.wzj.soopin.content.enums.YesOrNo;
|
||||
import com.wzj.soopin.content.mapper.CommentMapper;
|
||||
import com.wzj.soopin.content.mapper.MyLikedVlogMapper;
|
||||
import com.wzj.soopin.content.mapper.UsersMapper;
|
||||
import com.wzj.soopin.member.domain.vo.MemberVO;
|
||||
import com.wzj.soopin.member.mapper.MemberMapper;
|
||||
import com.wzj.soopin.content.mapper.VlogMapper;
|
||||
import com.wzj.soopin.content.mapper.VlogMapperCustom;
|
||||
@ -30,6 +31,7 @@ import com.wzj.soopin.content.utils.Sid;
|
||||
import com.wzj.soopin.content.utils.TencentCloudUtil;
|
||||
import com.wzj.soopin.member.service.IFansService;
|
||||
import com.wzj.soopin.content.convert.VlogConvert;
|
||||
import com.wzj.soopin.member.service.IMemberService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dromara.common.core.domain.model.LoginUser;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
@ -38,10 +40,6 @@ import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.dromara.system.service.ISysMessageService;
|
||||
import org.dromara.system.service.ISysMessageTemplateService;
|
||||
import org.dromara.system.domain.bo.SysMessageBo;
|
||||
import org.dromara.system.domain.vo.SysMessageTemplateVo;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
|
||||
import java.time.Instant;
|
||||
@ -80,10 +78,7 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
@Autowired
|
||||
private MemberMapper memberMapper;
|
||||
@Autowired
|
||||
private ISysMessageService sysMessageService;
|
||||
@Autowired
|
||||
private ISysMessageTemplateService templateService;
|
||||
|
||||
private IMemberService memberService;
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void updateVlogStatus(String fileId, Integer status, String reason) {
|
||||
@ -100,23 +95,23 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
|
||||
// 2. 选择模板(假设你有模板ID,实际可配置到常量或数据库)
|
||||
Long templateId = (status == 1) ? 1938491493736902658L : 1938491899007332353L; // 1001=审核通过模板,1002=驳回模板
|
||||
SysMessageTemplateVo template = templateService.selectTemplateById(templateId);
|
||||
if (template == null) return;
|
||||
|
||||
// 3. 参数替换
|
||||
String content = template.getTemplateContent()
|
||||
.replace("${videoTitle}", vlog.getTitle() == null ? "" : vlog.getTitle())
|
||||
.replace("${reason}", reason == null ? "" : reason);
|
||||
|
||||
// 4. 构造消息对象
|
||||
SysMessageBo messageBo = new SysMessageBo();
|
||||
messageBo.setTitle(template.getTitle());
|
||||
messageBo.setContent(content);
|
||||
messageBo.setSenderId(1L); // 系统管理员
|
||||
// 可根据需要设置更多字段
|
||||
|
||||
// 5. 发送消息
|
||||
sysMessageService.sendMessageToUser(messageBo, Long.valueOf(uploaderId));
|
||||
// SysMessageTemplateVo template = templateService.selectTemplateById(templateId);
|
||||
// if (template == null) return;
|
||||
//
|
||||
// // 3. 参数替换
|
||||
// String content = template.getTemplateContent()
|
||||
// .replace("${videoTitle}", vlog.getTitle() == null ? "" : vlog.getTitle())
|
||||
// .replace("${reason}", reason == null ? "" : reason);
|
||||
//
|
||||
// // 4. 构造消息对象
|
||||
// SysMessageBo messageBo = new SysMessageBo();
|
||||
// messageBo.setTitle(template.getTitle());
|
||||
// messageBo.setContent(content);
|
||||
// messageBo.setSenderId(1L); // 系统管理员
|
||||
// // 可根据需要设置更多字段
|
||||
//
|
||||
// // 5. 发送消息
|
||||
// sysMessageService.sendMessageToUser(messageBo, Long.valueOf(uploaderId));
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@ -162,7 +157,7 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
if (StringUtils.isNotBlank(status)) {
|
||||
queryWrapper.eq(Vlog::getStatus, status);
|
||||
}
|
||||
// Handle blocked videos
|
||||
// 去掉黑名单的视频
|
||||
if (StringUtils.isNotBlank(userId)) {
|
||||
String redisKey = REDIS_VIDEO_BLOCK + ":" + userId;
|
||||
if (redis.keyIsExist(redisKey)) {
|
||||
@ -183,7 +178,7 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle blocked users
|
||||
// 去掉黑名单的用户
|
||||
if (StringUtils.isNotBlank(userId)) {
|
||||
String redisKey = REDIS_USER_BLOCK + ":" + userId;
|
||||
if (redis.keyIsExist(redisKey)) {
|
||||
@ -196,7 +191,7 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
String memberId = (String) reportMap.get("MemberId");
|
||||
blockUserList.add(memberId);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
if (!blockUserList.isEmpty()) {
|
||||
@ -204,6 +199,27 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 去掉已读的视频
|
||||
if (StringUtils.isNotBlank(userId)) {
|
||||
String redisKey = REDIS_USER_READ_VLOG + ":" + userId;
|
||||
if (redis.keyIsExist(redisKey)) {
|
||||
List<String> readVlogList = new ArrayList<>();
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
List<String> reports = redis.lrange(redisKey, 0, -1);
|
||||
for (String report : reports) {
|
||||
try {
|
||||
Map<String, Object> reportMap = objectMapper.readValue(report, new TypeReference<Map<String, Object>>() {});
|
||||
String memberId = (String) reportMap.get("MemberId");
|
||||
readVlogList.add(memberId);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
if (!readVlogList.isEmpty()) {
|
||||
queryWrapper.notIn(Vlog::getMemberId, readVlogList);
|
||||
}
|
||||
}
|
||||
}
|
||||
Page<Vlog> vlogPage = vlogMapper.selectPage(pageParam, queryWrapper);
|
||||
List<Vlog> vlogList = vlogPage.getRecords();
|
||||
List<IndexVlogVO> voList = vlogList.stream().map(v -> {
|
||||
@ -214,28 +230,15 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
}
|
||||
vo.setLikeCounts(getVlogBeLikedCounts(v.getId()));
|
||||
vo.setCommentsCounts(getVlogComment(v.getId()));
|
||||
MemberVO m =memberService.getMemberInfo(vo.getMemberId());
|
||||
if (m != null) {
|
||||
vo.setAvatar(m.getAvatar());
|
||||
vo.setNickname(m.getNickname());
|
||||
}
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
// 批量补充作者信息(头像/昵称)
|
||||
if (!vlogList.isEmpty()) {
|
||||
List<String> memberIds = vlogList.stream()
|
||||
.map(Vlog::getMemberId)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (!memberIds.isEmpty()) {
|
||||
List<Member> members = memberMapper.selectList(new LambdaQueryWrapper<Member>().in(Member::getId, memberIds));
|
||||
Map<String, Member> memberMap = members.stream().collect(Collectors.toMap(m -> String.valueOf(m.getId()), m -> m, (a, b) -> a));
|
||||
voList.forEach(vo -> {
|
||||
Member m = memberMap.get(vo.getMemberId());
|
||||
if (m != null) {
|
||||
vo.setAvatar(m.getAvatar());
|
||||
vo.setNickname(m.getNickname());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 封装分页结果
|
||||
Page<IndexVlogVO> gridResult = new Page<IndexVlogVO>();
|
||||
@ -397,23 +400,23 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
if (vlog != null) {
|
||||
String vlogerId = vlog.getMemberId();
|
||||
if (!userId.equals(vlogerId)) {
|
||||
Long templateId = 1938491299175723009L;
|
||||
SysMessageTemplateVo template = templateService.selectTemplateById(templateId);
|
||||
if (template != null) {
|
||||
// 查询点赞用户昵称
|
||||
Member liker = memberMapper.selectById(userId);
|
||||
String likerNickname = liker != null && liker.getNickname() != null ? liker.getNickname() : "";
|
||||
|
||||
String content = template.getTemplateContent()
|
||||
.replace("${videoTitle}", vlog.getTitle() == null ? "" : vlog.getTitle())
|
||||
.replace("${liker}", userId)
|
||||
.replace("${likerNickname}", likerNickname);
|
||||
SysMessageBo messageBo = new SysMessageBo();
|
||||
messageBo.setTitle(template.getTitle());
|
||||
messageBo.setContent(content);
|
||||
messageBo.setSenderId(Long.valueOf(userId));
|
||||
sysMessageService.sendMessageToUser(messageBo, Long.valueOf(vlogerId));
|
||||
}
|
||||
// Long templateId = 1938491299175723009L;
|
||||
// SysMessageTemplateVo template = templateService.selectTemplateById(templateId);
|
||||
// if (template != null) {
|
||||
// // 查询点赞用户昵称
|
||||
// Member liker = memberMapper.selectById(userId);
|
||||
// String likerNickname = liker != null && liker.getNickname() != null ? liker.getNickname() : "";
|
||||
//
|
||||
// String content = template.getTemplateContent()
|
||||
// .replace("${videoTitle}", vlog.getTitle() == null ? "" : vlog.getTitle())
|
||||
// .replace("${liker}", userId)
|
||||
// .replace("${likerNickname}", likerNickname);
|
||||
// SysMessageBo messageBo = new SysMessageBo();
|
||||
// messageBo.setTitle(template.getTitle());
|
||||
// messageBo.setContent(content);
|
||||
// messageBo.setSenderId(Long.valueOf(userId));
|
||||
// sysMessageService.sendMessageToUser(messageBo, Long.valueOf(vlogerId));
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.wzj.soopin.content.task;
|
||||
|
||||
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
|
||||
import com.wzj.soopin.content.service.VlogService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -8,11 +9,12 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 视频相关定时任务
|
||||
*
|
||||
*
|
||||
* @author wzj
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@JobExecutor(name = "vlogHotDataTask" )
|
||||
public class VlogScheduledTask {
|
||||
|
||||
@Autowired
|
||||
@ -22,8 +24,7 @@ public class VlogScheduledTask {
|
||||
* 每天12点定时查询点赞最多的100条视频并存储到Redis
|
||||
* cron表达式:0 0 12 * * ? (每天12点执行)
|
||||
*/
|
||||
@Scheduled(cron = "0 0 12 * * ?")
|
||||
public void cacheTopLikedVlogs() {
|
||||
public void jobExecute() {
|
||||
log.info("开始执行定时任务:查询点赞最多的100条视频并存储到Redis");
|
||||
try {
|
||||
vlogService.cacheTopLikedVlogs(100);
|
||||
@ -32,4 +33,4 @@ public class VlogScheduledTask {
|
||||
log.error("定时任务执行失败:缓存点赞最多视频到Redis时发生异常", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,18 @@
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-member</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-content</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-doc</artifactId>
|
||||
@ -34,6 +45,10 @@
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-translation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-rabbitmq</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- OSS功能模块 -->
|
||||
<dependency>
|
||||
|
@ -0,0 +1,48 @@
|
||||
package org.dromara.im.enums;
|
||||
|
||||
public enum MessageActionEnum {
|
||||
|
||||
NEW_FOUCS(1,"新的关注"), //新的关注
|
||||
SYSTEM_NOTIFY(2, "系统->通知"), // 系统->通知
|
||||
SYSTEM_REPORT(3, "系统->举报下架(视频,视频评论) 视频评论"), // 系统->举报下架(视频,视频评论) 视频评论
|
||||
SYSTEM_CHECK(4, "系统->审核结果(复审,驳回 ,通过)"), // 系统->审核结果(复审,驳回 ,通过)
|
||||
SYSTEM_PUSH(5, "系统->推广类的"), //系统->推广类的
|
||||
INTERACTION_COMMENT(6, "互动->评论"), //互动->评论
|
||||
INTERACTION_AT(7, "互动->视频评论中的@"), //互动->视频评论中的@
|
||||
INTERACTION_LIKE(8, "互动->点赞"), //互动->点赞
|
||||
INTERACTION_REPLY(9, "互动->评论回复"), //互动->评论回复
|
||||
ORDER_RECHARGE(10, "订单->充值 online"), //订单->充值 online
|
||||
ORDER_PAY(11, "订单->订单交易成功通知 online"), //订单->订单交易成功通知 online
|
||||
ORDER_REFUND(12, "订单->退款结果通知"), //订单->退款结果通知
|
||||
GROUP_NOTIFY_CHECK(13, "群通知->进群申请 online"), //群通知->进群申请 online
|
||||
GROUP_NOTIFY_ACCEPT(14, "群通知->进群审核审核通过 online"), // 群通知->进群审核审核通过 online
|
||||
GROUP_NOTIFY_FAIL(15, "群通知->进群审核审核拒绝 online"), // 群通知->进群审核审核拒绝 online
|
||||
GROUP_NOTIFY_LEAVE_UP(16, "群通知->群升级为达人群通知"), // 群通知->群升级为达人群通知
|
||||
GROUP_NOTIFY_LEAVE_DOWN(17, "群通知->群降级为普通群通知"); // 群通知->群降级为普通群通知
|
||||
|
||||
private int code;
|
||||
private String account;
|
||||
private String desc;
|
||||
|
||||
MessageActionEnum(int code, String desc) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public static MessageActionEnum getByCode(int code) {
|
||||
for (MessageActionEnum actionEnum : values()) {
|
||||
if (actionEnum.getCode() == code) {
|
||||
return actionEnum;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package org.dromara.im.enums;
|
||||
|
||||
public enum MessageScopeEnum {
|
||||
/**
|
||||
* 全部用户
|
||||
*/
|
||||
ALL(1, "全部"),
|
||||
/**
|
||||
* 系统用户
|
||||
*/
|
||||
USER(2, "用户"),
|
||||
/**
|
||||
* 会员
|
||||
*/
|
||||
MEMBER(3, "会员"),
|
||||
|
||||
/**
|
||||
* 租户
|
||||
*/
|
||||
TENANT(4, "租户");
|
||||
private int code;
|
||||
private String desc;
|
||||
|
||||
private MessageScopeEnum(int code, String desc) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package org.dromara.soopin.im.consumer;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.rabbitmq.config.properties.RabbitMQConfig;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
@Slf4j
|
||||
@Component
|
||||
public class IMMessageConsumer {
|
||||
@RabbitListener(queues = RabbitMQConfig.TOPIC_QUEUE_NAME)
|
||||
public void handleDirectMessage(String message, Channel channel, Message amqpMessage) throws IOException {
|
||||
try {
|
||||
log.info("接收到直连队列消息: {}", message);
|
||||
// 业务处理逻辑
|
||||
channel.basicAck(amqpMessage.getMessageProperties().getDeliveryTag(), false);
|
||||
} catch (Exception e) {
|
||||
log.error("消息处理失败", e);
|
||||
channel.basicNack(amqpMessage.getMessageProperties().getDeliveryTag(), false, true);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +1,24 @@
|
||||
package org.dromara.system.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
//import com.wzj.soopin.member.domain.po.Member;
|
||||
//import com.wzj.soopin.member.mapper.MemberMapper;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.system.domain.SysMessage;
|
||||
import org.dromara.system.domain.bo.SysMessageBo;
|
||||
import org.dromara.system.domain.vo.SysMessageTemplateVo;
|
||||
import org.dromara.system.domain.vo.SysMessageVo;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
import org.dromara.system.service.ISysMessageService;
|
||||
import org.dromara.system.service.ISysMessageTemplateService;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 消息管理
|
||||
*
|
||||
@ -44,9 +31,6 @@ import java.util.List;
|
||||
public class SysMessageController extends BaseController {
|
||||
|
||||
private final ISysMessageService messageService;
|
||||
private final ISysUserService userService;
|
||||
private final ISysMessageTemplateService templateService;
|
||||
// private final MemberMapper umsMemberMapper;
|
||||
|
||||
/**
|
||||
* 获取当前用户ID
|
||||
@ -80,6 +64,7 @@ public class SysMessageController extends BaseController {
|
||||
return R.ok(messageService.selectMessageById(id));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*/
|
||||
@ -88,261 +73,17 @@ public class SysMessageController extends BaseController {
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/send")
|
||||
public R<Void> send(@RequestBody SysMessageBo bo) {
|
||||
// 设置发送者ID为当前登录用户ID
|
||||
bo.setSenderId(getUserId());
|
||||
|
||||
// 如果提供了模板ID,则从模板中获取标题和内容
|
||||
Long templateId = bo.getTemplateId();
|
||||
if (templateId != null) {
|
||||
SysMessageTemplateVo template = templateService.selectTemplateById(templateId);
|
||||
if (template != null) {
|
||||
// 使用模板的标题和内容
|
||||
bo.setTitle(template.getTitle());
|
||||
bo.setContent(template.getTemplateContent());
|
||||
} else {
|
||||
return R.fail("未找到指定的消息模板");
|
||||
}
|
||||
if(templateId == null){
|
||||
return R.fail("模板不能为空");
|
||||
}
|
||||
|
||||
// 验证消息内容是否为空
|
||||
if (StringUtils.isBlank(bo.getContent())) {
|
||||
return R.fail("消息内容不能为空");
|
||||
}
|
||||
|
||||
// 验证发送范围是否为空
|
||||
List<String> sendScope = bo.getSendScope();
|
||||
if (sendScope == null || sendScope.isEmpty()) {
|
||||
return R.fail("发送范围不能为空");
|
||||
}
|
||||
|
||||
// 处理接收者
|
||||
List<String> userIdStrings = new ArrayList<>();
|
||||
|
||||
// 根据logmess值处理不同类型的消息接收者
|
||||
Integer logmess = bo.getLogmess();
|
||||
if (logmess != null) {
|
||||
// 获取发送范围作为主要处理对象
|
||||
if (sendScope == null || sendScope.isEmpty()) {
|
||||
return R.fail("发送范围不能为空");
|
||||
}
|
||||
|
||||
String scope = sendScope.get(0); // 获取第一个范围值
|
||||
|
||||
switch (logmess) {
|
||||
case 1: // 指定角色
|
||||
// 当logmess=1时,sendScope接收的是角色ID或特殊标识
|
||||
if ("all".equals(scope)) {
|
||||
// 全部会员用户(查ums_member表)
|
||||
// List<Member> members = umsMemberMapper.selectList(
|
||||
// new QueryWrapper<Member>().eq("status", 1)
|
||||
// );
|
||||
// userIdStrings = members.stream().map(m -> String.valueOf(m.getId())).toList();
|
||||
} else if ("expert".equals(scope) || "merchant".equals(scope) || "user".equals(scope)) {
|
||||
List<SysUserVo> users = userService.selectUserListByDept(null);
|
||||
List<Long> userIds;
|
||||
switch (scope) {
|
||||
case "expert":
|
||||
userIds = users.stream()
|
||||
.filter(user -> "expert".equals(user.getUserType()))
|
||||
.map(SysUserVo::getUserId)
|
||||
.toList();
|
||||
break;
|
||||
case "merchant":
|
||||
userIds = users.stream()
|
||||
.filter(user -> "merchant".equals(user.getUserType()))
|
||||
.map(SysUserVo::getUserId)
|
||||
.toList();
|
||||
break;
|
||||
case "user":
|
||||
userIds = users.stream()
|
||||
.filter(user -> "user".equals(user.getUserType()))
|
||||
.map(SysUserVo::getUserId)
|
||||
.toList();
|
||||
break;
|
||||
default:
|
||||
userIds = List.of();
|
||||
}
|
||||
userIdStrings = userIds.stream().map(String::valueOf).toList();
|
||||
} else if (StringUtils.isNotBlank(scope)) {
|
||||
try {
|
||||
// 尝试将scope解析为角色ID
|
||||
Long roleId = Long.parseLong(scope);
|
||||
List<Long> userIds = userService.selectUserIdsByRoleId(roleId);
|
||||
if (userIds != null && !userIds.isEmpty()) {
|
||||
userIdStrings = userIds.stream().map(String::valueOf).toList();
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
return R.fail("角色ID格式不正确");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: // 指定用户
|
||||
// 当logmess=2时,sendScope接收的是用户ID数组
|
||||
if (sendScope != null && !sendScope.isEmpty()) {
|
||||
userIdStrings = new ArrayList<>();
|
||||
for (String userId : sendScope) {
|
||||
if (StringUtils.isNotBlank(userId)) {
|
||||
userIdStrings.add(userId);
|
||||
}
|
||||
}
|
||||
} else if (bo.getUserIds() != null && !bo.getUserIds().isEmpty()) {
|
||||
// 如果没有指定scope但有userIds,使用userIds
|
||||
userIdStrings = bo.getUserIds().stream().map(String::valueOf).toList();
|
||||
}
|
||||
break;
|
||||
case 3: // 指定群组/部门
|
||||
// 当logmess=3时,sendScope接收的是群组/部门ID
|
||||
if (StringUtils.isNotBlank(scope)) {
|
||||
try {
|
||||
Long deptId = Long.parseLong(scope);
|
||||
List<SysUserVo> users = userService.selectUserListByDept(deptId);
|
||||
if (users != null && !users.isEmpty()) {
|
||||
userIdStrings = users.stream()
|
||||
.map(user -> String.valueOf(user.getUserId()))
|
||||
.toList();
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
return R.fail("群组/部门ID格式不正确");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return R.fail("不支持的消息类型");
|
||||
}
|
||||
} else {
|
||||
// 如果没有指定logmess,则使用原有的处理逻辑
|
||||
if (sendScope == null || sendScope.isEmpty()) {
|
||||
return R.fail("发送范围不能为空");
|
||||
}
|
||||
|
||||
String scope = sendScope.get(0); // 获取第一个范围值
|
||||
|
||||
// 如果是群发消息类型,则根据类型筛选用户
|
||||
if ("all".equals(scope) || "expert".equals(scope) || "merchant".equals(scope) || "user".equals(scope)) {
|
||||
List<SysUserVo> users = userService.selectUserListByDept(null);
|
||||
List<Long> userIds;
|
||||
|
||||
switch (scope) {
|
||||
case "all":
|
||||
// 全部用户
|
||||
userIds = users.stream().map(SysUserVo::getUserId).toList();
|
||||
break;
|
||||
case "expert":
|
||||
// 达人
|
||||
userIds = users.stream()
|
||||
.filter(user -> "expert".equals(user.getUserType()))
|
||||
.map(SysUserVo::getUserId)
|
||||
.toList();
|
||||
break;
|
||||
case "merchant":
|
||||
// 商户
|
||||
userIds = users.stream()
|
||||
.filter(user -> "merchant".equals(user.getUserType()))
|
||||
.map(SysUserVo::getUserId)
|
||||
.toList();
|
||||
break;
|
||||
case "user":
|
||||
// 普通用户
|
||||
userIds = users.stream()
|
||||
.filter(user -> "user".equals(user.getUserType()))
|
||||
.map(SysUserVo::getUserId)
|
||||
.toList();
|
||||
break;
|
||||
default:
|
||||
userIds = List.of();
|
||||
}
|
||||
userIdStrings = userIds.stream().map(String::valueOf).toList();
|
||||
} else {
|
||||
// 直接使用指定的接收者ID
|
||||
if (bo.getUserIds() != null && !bo.getUserIds().isEmpty()) {
|
||||
// 如果userIds不为空,使用它
|
||||
userIdStrings = bo.getUserIds().stream().map(String::valueOf).toList();
|
||||
} else if (sendScope != null && !sendScope.isEmpty()) {
|
||||
// 如果userIds为空但sendScope不为空,将sendScope作为用户ID使用
|
||||
userIdStrings = sendScope;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有找到接收者,返回失败
|
||||
if (userIdStrings.isEmpty()) {
|
||||
return R.fail("未找到消息接收者");
|
||||
}
|
||||
|
||||
// 判断是否为定时消息,若是则注册SnailJob单次任务
|
||||
// if (bo.getScheduledTime() != null && bo.getScheduledTime().after(new java.util.Date())) {
|
||||
// // 先保存消息,获取ID
|
||||
// SysMessage entity = bo.toEntity();
|
||||
// entity.setStatus("0"); // 未发送
|
||||
// messageService.getBaseMapper().insert(entity);
|
||||
// // 创建SnailJob单次任务
|
||||
// org.dromara.system.job.SnailJobApiUtil.createSingleJob(entity.getId(), entity.getScheduledTime());
|
||||
// // 关联用户
|
||||
// for (String userId : userIdStrings) {
|
||||
// org.dromara.system.domain.SysMessageUser messageUser = new org.dromara.system.domain.SysMessageUser();
|
||||
// messageUser.setMessageId(entity.getId());
|
||||
// messageUser.setUserId(Long.valueOf(userId));
|
||||
// messageUser.setIsRead(false);
|
||||
// // 这里假设有messageUserMapper可用,实际应通过service或mapper注入
|
||||
// // messageUserMapper.insert(messageUser);
|
||||
// }
|
||||
// return toAjax(1);
|
||||
// }
|
||||
|
||||
return toAjax(messageService.sendMessageToUsers(bo, userIdStrings));
|
||||
messageService.send(bo);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记消息为已读
|
||||
*/
|
||||
// @SaCheckPermission("system:message:mark")
|
||||
@Log(title = "消息管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/mark/{id}")
|
||||
public R<Void> markAsRead(@NotNull(message = "消息ID不能为空") @PathVariable Long id) {
|
||||
return toAjax(messageService.markAsRead(id, getUserId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除消息
|
||||
*
|
||||
* @param ids 消息ID串
|
||||
*/
|
||||
// @SaCheckPermission("system:message:remove")
|
||||
@Log(title = "消息管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "消息ID不能为空") @PathVariable Long[] ids) {
|
||||
return toAjax(messageService.deleteMessageByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取未读消息列表
|
||||
*/
|
||||
// @SaCheckPermission("system:message:list")
|
||||
@Tag(name = "查询未读消息列表")
|
||||
@PostMapping("/unread")
|
||||
public R<Page<SysMessageVo>> unreadList(@RequestBody Page<SysMessage> page) {
|
||||
Page<SysMessageVo> unreadPage = messageService.selectUnreadMessagesPage(getUserId(), page);
|
||||
return R.ok(unreadPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已读消息列表
|
||||
*/
|
||||
// @SaCheckPermission("system:message:list")
|
||||
@Tag(name = "查询已读消息列表")
|
||||
@PostMapping("/read")
|
||||
public R<Page<SysMessageVo>> readList(@RequestBody Page<SysMessage> page) {
|
||||
Page<SysMessageVo> readPage = messageService.selectReadMessagesPage(getUserId(), page);
|
||||
return R.ok(readPage);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 获取用户列表
|
||||
// */
|
||||
//// @SaCheckPermission("system:message:list")
|
||||
// @GetMapping("/user/list")
|
||||
// public R<List<SysUserVo>> getUserList(@RequestParam(required = false) String keyword) {
|
||||
// // 无论是否有关键词,都查询 ums_member 表中的用户信息
|
||||
// return R.ok(userService.selectMemberUsers(keyword));
|
||||
// }
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.system.converter.SysMessageTemplateConvert;
|
||||
import org.dromara.system.domain.SysMessageTemplate;
|
||||
import org.dromara.system.domain.bo.SysMessageTemplateBo;
|
||||
import org.dromara.system.domain.vo.SysMessageTemplateVo;
|
||||
@ -39,6 +40,8 @@ public class SysMessageTemplateController extends BaseController {
|
||||
|
||||
private final ISysMessageTemplateService templateService;
|
||||
|
||||
private final SysMessageTemplateConvert convert;
|
||||
|
||||
/**
|
||||
* 查询消息模板列表
|
||||
*/
|
||||
@ -63,7 +66,7 @@ public class SysMessageTemplateController extends BaseController {
|
||||
SysMessageTemplate template = templateService.getById(id);
|
||||
return R.ok(MapstructUtils.convert(template, SysMessageTemplateVo.class));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据名称查询消息模板列表(不分页)
|
||||
*
|
||||
@ -88,7 +91,7 @@ public class SysMessageTemplateController extends BaseController {
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody SysMessageTemplateBo bo) {
|
||||
return toAjax(templateService.save(bo.toEntity()));
|
||||
return toAjax(templateService.save(convert.toPo(bo)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,7 +102,7 @@ public class SysMessageTemplateController extends BaseController {
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysMessageTemplateBo bo) {
|
||||
return toAjax(templateService.updateById(bo.toEntity()));
|
||||
return toAjax(templateService.updateById(convert.toPo(bo)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,86 @@
|
||||
package org.dromara.system.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.system.domain.SysMessage;
|
||||
import org.dromara.system.domain.vo.SysMessageVo;
|
||||
import org.dromara.system.service.ISysMessageService;
|
||||
import org.dromara.system.service.ISysMessageTemplateService;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.dromara.system.service.impl.SystemMessageUserService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import static org.dromara.common.satoken.utils.LoginHelper.getUserId;
|
||||
|
||||
/**
|
||||
* 消息管理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Validated
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/system/message/task")
|
||||
public class SysMessageUserController extends BaseController {
|
||||
|
||||
private final ISysMessageService messageService;
|
||||
private final ISysUserService userService;
|
||||
private final ISysMessageTemplateService templateService;
|
||||
|
||||
private final SystemMessageUserService systemMessageTaskService;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取未读消息列表
|
||||
*/
|
||||
// @SaCheckPermission("system:message:list")
|
||||
@Tag(name = "查询未读消息列表")
|
||||
@PostMapping("/unread")
|
||||
public R<Page<SysMessageVo>> unreadList(@RequestBody Page<SysMessage> page) {
|
||||
Page<SysMessageVo> unreadPage = messageService.selectUnreadMessagesPage(getUserId(), page);
|
||||
return R.ok(unreadPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已读消息列表
|
||||
*/
|
||||
// @SaCheckPermission("system:message:list")
|
||||
@Tag(name = "查询已读消息列表")
|
||||
@PostMapping("/read")
|
||||
public R<Page<SysMessageVo>> readList(@RequestBody Page<SysMessage> page) {
|
||||
Page<SysMessageVo> readPage = messageService.selectReadMessagesPage(getUserId(), page);
|
||||
return R.ok(readPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记消息为已读
|
||||
*/
|
||||
// @SaCheckPermission("system:message:mark")
|
||||
@Log(title = "消息管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/mark/{id}")
|
||||
public R<Void> markAsRead(@NotNull(message = "消息ID不能为空") @PathVariable Long id) {
|
||||
return toAjax(messageService.markAsRead(id, getUserId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除消息
|
||||
*
|
||||
* @param ids 消息ID串
|
||||
*/
|
||||
// @SaCheckPermission("system:message:remove")
|
||||
@Log(title = "消息管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "消息ID不能为空") @PathVariable Long[] ids) {
|
||||
return toAjax(messageService.deleteMessageByIds(ids));
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +1,10 @@
|
||||
package org.dromara.system.converter;
|
||||
|
||||
import org.dromara.common.web.core.BaseConverter;
|
||||
import org.dromara.system.domain.SysMessage;
|
||||
import org.dromara.system.domain.bo.SysMessageBo;
|
||||
import org.dromara.system.domain.vo.SysMessageVo;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 消息对象转换器
|
||||
@ -13,27 +12,6 @@ import java.util.List;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface SysMessageConvert {
|
||||
public interface SysMessageConvert extends BaseConverter<SysMessageVo, SysMessageBo,SysMessage> {
|
||||
|
||||
SysMessageConvert INSTANCE = Mappers.getMapper(SysMessageConvert.class);
|
||||
|
||||
/**
|
||||
* SysMessage转SysMessageVo
|
||||
*/
|
||||
SysMessageVo convert(SysMessage sysMessage);
|
||||
|
||||
/**
|
||||
* SysMessage列表转SysMessageVo列表
|
||||
*/
|
||||
List<SysMessageVo> convertList(List<SysMessage> sysMessageList);
|
||||
|
||||
/**
|
||||
* SysMessageVo转SysMessage
|
||||
*/
|
||||
SysMessage convert(SysMessageVo sysMessageVo);
|
||||
|
||||
/**
|
||||
* SysMessageVo列表转SysMessage列表
|
||||
*/
|
||||
List<SysMessage> convertListVoToEntity(List<SysMessageVo> sysMessageVoList);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package org.dromara.system.converter;
|
||||
|
||||
import org.dromara.common.web.core.BaseConverter;
|
||||
import org.dromara.system.domain.SysMessage;
|
||||
import org.dromara.system.domain.SysMessageTemplate;
|
||||
import org.dromara.system.domain.bo.SysMessageBo;
|
||||
import org.dromara.system.domain.bo.SysMessageTemplateBo;
|
||||
import org.dromara.system.domain.vo.SysMessageTemplateVo;
|
||||
import org.dromara.system.domain.vo.SysMessageVo;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
/**
|
||||
* 消息对象转换器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface SysMessageTemplateConvert extends BaseConverter<SysMessageTemplateVo, SysMessageTemplateBo, SysMessageTemplate> {
|
||||
|
||||
}
|
@ -43,7 +43,7 @@ public class SysMessage extends BaseAudit {
|
||||
private String subType;
|
||||
|
||||
/** 发送者ID */
|
||||
private Long senderId;
|
||||
private String senderId;
|
||||
|
||||
/** 定时发送时间 */
|
||||
private Date scheduledTime;
|
||||
@ -51,6 +51,9 @@ public class SysMessage extends BaseAudit {
|
||||
/** 状态(0未发送 1已发送) */
|
||||
private String status;
|
||||
|
||||
/** 发送范围(1:全部用户, 2:按用户类型, 3:指定用户) */
|
||||
private Integer sendScope;
|
||||
|
||||
/** 扩展参数 */
|
||||
@TableField(exist = false)
|
||||
private Map<String, Object> params = new HashMap<>();
|
||||
@ -62,4 +65,10 @@ public class SysMessage extends BaseAudit {
|
||||
/** 模板参数 */
|
||||
@TableField(exist = false)
|
||||
private Map<String, Object> templateParams;
|
||||
/**
|
||||
* 模板ID
|
||||
*/
|
||||
private Long templateId;
|
||||
|
||||
private String ext;
|
||||
}
|
||||
|
@ -29,37 +29,39 @@ public class SysMessageTemplate extends BaseAudit {
|
||||
/**
|
||||
* 模板类型(0通知 1公告)
|
||||
*/
|
||||
private String templateType;
|
||||
private String type;
|
||||
private String title;
|
||||
|
||||
// /**
|
||||
// * 模板编码
|
||||
// */
|
||||
// private String templateCode;
|
||||
|
||||
|
||||
/**
|
||||
* 模板名称
|
||||
*/
|
||||
private String templateName;
|
||||
private String name;
|
||||
|
||||
|
||||
/**
|
||||
* 模板内容
|
||||
*/
|
||||
private String templateContent;
|
||||
private String content;
|
||||
|
||||
// /**
|
||||
// * 模板参数
|
||||
// */
|
||||
// private String templateParams;
|
||||
/**
|
||||
* 扩展参数
|
||||
*/
|
||||
private String ext;
|
||||
|
||||
/**
|
||||
* 状态(0正常 1停用)
|
||||
*/
|
||||
private String status;
|
||||
//
|
||||
// /**
|
||||
// * 备注
|
||||
// */
|
||||
// private String remark;
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
*/
|
||||
private Integer action;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String description;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.dromara.system.domain.bo;
|
||||
|
||||
import cn.hutool.core.map.MapWrapper;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
@ -7,6 +8,7 @@ import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.core.domain.BaseBO;
|
||||
import org.dromara.common.core.domain.model.BaseAudit;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
@ -18,8 +20,12 @@ import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import org.dromara.system.domain.SysMessageTemplate;
|
||||
|
||||
/**
|
||||
* 消息业务对象
|
||||
@ -29,12 +35,15 @@ import com.baomidou.mybatisplus.annotation.TableField;
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ExcelIgnoreUnannotated
|
||||
public class SysMessageBo extends BaseAudit {
|
||||
public class SysMessageBo extends BaseBO<SysMessage> {
|
||||
|
||||
/** 主键ID */
|
||||
@ExcelProperty(value = "消息ID")
|
||||
private Long id;
|
||||
|
||||
/** 发送者ID */
|
||||
private String senderId;
|
||||
|
||||
/** 消息标题 */
|
||||
// @NotBlank(message = "消息标题不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
@Size(min = 0, max = 100, message = "消息标题长度不能超过100个字符")
|
||||
@ -46,39 +55,21 @@ public class SysMessageBo extends BaseAudit {
|
||||
@ExcelProperty(value = "消息内容")
|
||||
private String content;
|
||||
|
||||
/** 消息类型(AUTO自动/MANUAL手动) */
|
||||
// @NotBlank(message = "消息类型不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
@ExcelProperty(value = "消息类型")
|
||||
private String msgType;
|
||||
|
||||
/** 触发条件 */
|
||||
@ExcelProperty(value = "触发条件")
|
||||
private String subType;
|
||||
|
||||
/** 发送者ID */
|
||||
@ExcelProperty(value = "发送者ID")
|
||||
private Long senderId;
|
||||
|
||||
/** 定时发送时间 */
|
||||
@ExcelProperty(value = "定时发送时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX", timezone = "Asia/Shanghai")
|
||||
private Date scheduledTime;
|
||||
|
||||
/** 发送范围(all:全部用户, userType:按用户类型, userIds:指定用户) */
|
||||
@NotEmpty(message = "发送范围不能为空", groups = { AddGroup.class })
|
||||
private List<String> sendScope;
|
||||
private Integer sendScope;
|
||||
|
||||
/** 接收用户ID列表 */
|
||||
private List<Long> userIds;
|
||||
private List<Long> idList;
|
||||
|
||||
|
||||
/** 是否发送给所有用户 */
|
||||
private Boolean sendToAll;
|
||||
|
||||
/** 扩展数据(JSON格式) */
|
||||
private String extraData;
|
||||
|
||||
/** 消息类型标识 1=指定角色 2=指定用户 3=指定群 */
|
||||
private Integer logmess;
|
||||
|
||||
|
||||
/** 模板ID */
|
||||
private Long templateId;
|
||||
@ -89,6 +80,42 @@ public class SysMessageBo extends BaseAudit {
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
|
||||
private String templateType;
|
||||
|
||||
|
||||
/**
|
||||
* 是否发送给所有用户
|
||||
*/
|
||||
private Boolean sendToAll;
|
||||
|
||||
/**
|
||||
* 消息类型标识 1=指定角色 2=指定用户 3=指定群
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
/** 定时发送时间 */
|
||||
@ExcelProperty(value = "定时发送时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX", timezone = "Asia/Shanghai")
|
||||
private Date scheduledTime;
|
||||
|
||||
/** 触发条件 */
|
||||
@ExcelProperty(value = "触发条件")
|
||||
private String subType;
|
||||
|
||||
/**
|
||||
* 模板ID
|
||||
*/
|
||||
private SysMessageTemplate template;
|
||||
|
||||
|
||||
private Map<String, Object> templateParams=new HashMap<>();
|
||||
|
||||
/** 消息类型(AUTO自动/MANUAL手动) */
|
||||
// @NotBlank(message = "消息类型不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
@ExcelProperty(value = "消息类型")
|
||||
private String msgType;
|
||||
|
||||
/** 创建时间-起始 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "UTC")
|
||||
private LocalDateTime startTime;
|
||||
@ -96,62 +123,20 @@ public class SysMessageBo extends BaseAudit {
|
||||
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "UTC")
|
||||
private LocalDateTime sendTime;
|
||||
|
||||
/** 模板类型编号(如1=关注,2=取消关注等) */
|
||||
@TableField(exist = false)
|
||||
private String templateType;
|
||||
|
||||
/** 模板参数 */
|
||||
@TableField(exist = false)
|
||||
private java.util.Map<String, Object> templateParams;
|
||||
|
||||
public String getTemplateType() {
|
||||
return templateType;
|
||||
}
|
||||
public void setTemplateType(String templateType) {
|
||||
this.templateType = templateType;
|
||||
}
|
||||
public java.util.Map<String, Object> getTemplateParams() {
|
||||
return templateParams;
|
||||
}
|
||||
public void setTemplateParams(java.util.Map<String, Object> templateParams) {
|
||||
this.templateParams = templateParams;
|
||||
}
|
||||
/**
|
||||
* 消息参数
|
||||
*/
|
||||
private Map<String, Object> params;
|
||||
|
||||
/**
|
||||
* 转换为查询条件
|
||||
*/
|
||||
@Override
|
||||
public LambdaQueryWrapper<SysMessage> toWrapper() {
|
||||
LambdaQueryWrapper<SysMessage> lqw = new LambdaQueryWrapper<>();
|
||||
lqw.like(StringUtils.isNotBlank(this.getTitle()), SysMessage::getTitle, this.getTitle())
|
||||
.like(StringUtils.isNotBlank(this.getContent()), SysMessage::getContent, this.getContent())
|
||||
.eq(StringUtils.isNotBlank(this.getMsgType()), SysMessage::getMsgType, this.getMsgType())
|
||||
.eq(StringUtils.isNotBlank(this.getSubType()), SysMessage::getSubType, this.getSubType())
|
||||
.eq(this.getSenderId() != null, SysMessage::getSenderId, this.getSenderId())
|
||||
.ge(this.getStartTime() != null, SysMessage::getCreateTime, this.getStartTime())
|
||||
.le(this.getSendTime() != null, SysMessage::getCreateTime, this.getSendTime())
|
||||
.orderByDesc(SysMessage::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为实体对象
|
||||
*/
|
||||
public SysMessage toEntity() {
|
||||
SysMessage entity = new SysMessage();
|
||||
entity.setId(this.getId());
|
||||
entity.setTitle(this.getTitle());
|
||||
entity.setContent(this.getContent());
|
||||
entity.setMsgType(this.getMsgType());
|
||||
entity.setSubType(this.getSubType());
|
||||
entity.setSenderId(this.getSenderId());
|
||||
entity.setScheduledTime(this.getScheduledTime());
|
||||
// entity.setExtraData(this.getExtraData());
|
||||
// entity.setStatus(this.getStatus());
|
||||
// entity.setRemark(this.getRemark());
|
||||
entity.setCreateBy(this.getCreateBy());
|
||||
entity.setCreateTime(this.getCreateTime());
|
||||
entity.setUpdateBy(this.getUpdateBy());
|
||||
entity.setUpdateTime(this.getUpdateTime());
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.dromara.common.core.domain.BaseBO;
|
||||
import org.dromara.common.core.domain.model.BaseAudit;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
@ -24,41 +25,40 @@ import jakarta.validation.constraints.Size;
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = SysMessageTemplate.class, reverseConvertGenerate = false)
|
||||
public class SysMessageTemplateBo extends BaseAudit {
|
||||
public class SysMessageTemplateBo extends BaseBO<SysMessageTemplate> {
|
||||
|
||||
/**
|
||||
* 模板ID
|
||||
*/
|
||||
@NotNull(message = "模板ID不能为空", groups = { EditGroup.class })
|
||||
@NotNull(message = "模板ID不能为空", groups = {EditGroup.class})
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 模板名称
|
||||
*/
|
||||
@NotBlank(message = "模板名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
@NotBlank(message = "模板名称不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(max = 100, message = "模板名称长度不能超过{max}个字符")
|
||||
private String templateName;
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 模板编码
|
||||
*/
|
||||
// @NotBlank(message = "模板编码不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
// @Size(max = 50, message = "模板编码长度不能超过{max}个字符")
|
||||
// private String templateCode;
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 模板类型(SMS=短信 MAIL=邮件 WECHAT=微信 SYSTEM=系统消息)
|
||||
*/
|
||||
@NotBlank(message = "模板类型不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
@NotBlank(message = "模板类型不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(max = 20, message = "模板类型长度不能超过{max}个字符")
|
||||
private String templateType;
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 模板内容
|
||||
*/
|
||||
@NotBlank(message = "模板内容不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String templateContent;
|
||||
@NotBlank(message = "模板内容不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 状态(0正常 1停用)
|
||||
@ -68,37 +68,24 @@ public class SysMessageTemplateBo extends BaseAudit {
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
// /**
|
||||
// * 备注
|
||||
// */
|
||||
// private String remark;
|
||||
|
||||
/**
|
||||
* 将当前对象转换为查询条件
|
||||
*/
|
||||
|
||||
private String ext;
|
||||
|
||||
private String action;
|
||||
|
||||
private String description;
|
||||
|
||||
|
||||
@Override
|
||||
public LambdaQueryWrapper<SysMessageTemplate> toWrapper() {
|
||||
LambdaQueryWrapper<SysMessageTemplate> lqw = new LambdaQueryWrapper<>();
|
||||
lqw.like(StringUtils.isNotBlank(templateName), SysMessageTemplate::getTemplateName, templateName)
|
||||
// .like(StringUtils.isNotBlank(templateCode), SysMessageTemplate::getTemplateCode, templateCode)
|
||||
.eq(StringUtils.isNotBlank(templateType), SysMessageTemplate::getTemplateType, templateType)
|
||||
return super.toWrapper().eq(id != null, SysMessageTemplate::getId, id)
|
||||
.eq(StringUtils.isNotBlank(type), SysMessageTemplate::getType, type)
|
||||
.eq(StringUtils.isNotBlank(type), SysMessageTemplate::getType, type)
|
||||
.eq(StringUtils.isNotBlank(name), SysMessageTemplate::getName, name)
|
||||
.eq(StringUtils.isNotBlank(content), SysMessageTemplate::getContent, content)
|
||||
.eq(StringUtils.isNotBlank(status), SysMessageTemplate::getStatus, status)
|
||||
.orderByDesc(SysMessageTemplate::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
.eq(StringUtils.isNotBlank(title), SysMessageTemplate::getTitle, title);
|
||||
|
||||
/**
|
||||
* 转换为实体对象
|
||||
*/
|
||||
public SysMessageTemplate toEntity() {
|
||||
SysMessageTemplate entity = new SysMessageTemplate();
|
||||
entity.setId(id);
|
||||
entity.setTemplateName(templateName);
|
||||
// entity.setTemplateCode(templateCode);
|
||||
entity.setTemplateType(templateType);
|
||||
entity.setTemplateContent(templateContent);
|
||||
entity.setStatus(status);
|
||||
entity.setTitle(title);
|
||||
// entity.setRemark(remark);
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.dromara.system.domain.vo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@ -16,11 +17,7 @@ import java.util.Date;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@AutoMapper(target = SysMessageTemplate.class)
|
||||
public class SysMessageTemplateVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 模板ID
|
||||
*/
|
||||
@ -29,17 +26,17 @@ public class SysMessageTemplateVo implements Serializable {
|
||||
/**
|
||||
* 模板类型(1通知 2公告 3消息)
|
||||
*/
|
||||
private String templateType;
|
||||
private String type;
|
||||
|
||||
// /**
|
||||
// * 模板编码
|
||||
// */
|
||||
// private String templateCode;
|
||||
/**
|
||||
* 模板编码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 模板名称
|
||||
*/
|
||||
private String templateName;
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 模板标题
|
||||
@ -49,12 +46,8 @@ public class SysMessageTemplateVo implements Serializable {
|
||||
/**
|
||||
* 模板内容
|
||||
*/
|
||||
private String templateContent;
|
||||
private String content;
|
||||
|
||||
// /**
|
||||
// * 模板参数
|
||||
// */
|
||||
// private String templateParams;
|
||||
|
||||
/**
|
||||
* 状态(0正常 1停用)
|
||||
@ -81,8 +74,21 @@ public class SysMessageTemplateVo implements Serializable {
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
// /**
|
||||
// * 备注
|
||||
// */
|
||||
// private String remark;
|
||||
/**
|
||||
* 扩展参数
|
||||
*/
|
||||
private String ext;
|
||||
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
*/
|
||||
private Integer action;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String description;
|
||||
|
||||
private String params;
|
||||
}
|
||||
|
@ -38,6 +38,9 @@ public class SysMessageVo implements Serializable {
|
||||
/** 消息内容 */
|
||||
@ExcelProperty(value = "消息内容")
|
||||
private String content;
|
||||
/** 扩展参数 */
|
||||
@ExcelProperty(value = "扩展参数")
|
||||
private String ext;
|
||||
|
||||
/** 消息类型(AUTO自动/MANUAL手动) */
|
||||
@ExcelProperty(value = "消息类型")
|
||||
@ -49,7 +52,7 @@ public class SysMessageVo implements Serializable {
|
||||
|
||||
/** 发送者ID */
|
||||
@ExcelProperty(value = "发送者ID")
|
||||
private Long senderId;
|
||||
private String senderId;
|
||||
|
||||
/** 发送者名称 */
|
||||
@ExcelProperty(value = "发送者")
|
||||
@ -59,9 +62,6 @@ public class SysMessageVo implements Serializable {
|
||||
@ExcelProperty(value = "定时发送时间")
|
||||
private Date scheduledTime;
|
||||
|
||||
// /** 状态(0正常 1停用) */
|
||||
// @ExcelProperty(value = "状态")
|
||||
// private String status;
|
||||
|
||||
/** 创建时间 */
|
||||
@ExcelProperty(value = "创建时间")
|
||||
@ -76,6 +76,7 @@ public class SysMessageVo implements Serializable {
|
||||
/** 更新者 */
|
||||
private String updateBy;
|
||||
|
||||
/** 扩展参数 */
|
||||
private Map<String, Object> params = new HashMap<>();
|
||||
private SysMessageTemplateVo template;
|
||||
|
||||
private Map<String, Object> params;
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
package org.dromara.system.event;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.google.gson.JsonObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.json.utils.JsonUtils;
|
||||
import org.dromara.system.consumer.MessageRocketMQConsumer;
|
||||
import org.dromara.system.domain.event.MessageEvent;
|
||||
@ -58,7 +61,7 @@ public class MessageEventListener {
|
||||
boolean tencentIMSendSuccess = false;
|
||||
try {
|
||||
// 消息发送者可能是系统或管理员,这里使用固定的管理员账号作为发送者
|
||||
String fromUserId = "administrator";
|
||||
String fromUserId = event.getMessage().getSenderId();
|
||||
String toUserId = userId; // 接收者是事件中的用户ID
|
||||
String content = event.getMessage().getContent(); // 只取content字段
|
||||
|
||||
@ -78,14 +81,15 @@ public class MessageEventListener {
|
||||
|
||||
// 扩展字段,可以在APP端获取
|
||||
String ext = null;
|
||||
if (event.getMessage().getParams() != null && !event.getMessage().getParams().isEmpty()) {
|
||||
ext = JsonUtils.toJsonString(event.getMessage().getParams());
|
||||
if (StringUtils.isNotBlank(event.getMessage().getExt())) {
|
||||
ext = JsonUtils.toJsonString(event.getMessage().getExt());
|
||||
}
|
||||
|
||||
String templateParams = event.getMessage().getTemplate().getParams();
|
||||
// 根据消息类型决定推送方式
|
||||
Map<String, Object> params = event.getMessage().getParams();
|
||||
JSONObject params = new JSONObject(templateParams);
|
||||
String pushType = null;
|
||||
if (params != null && params.containsKey("pushType")) {
|
||||
if (params != null && params.get("pushType")!=null) {
|
||||
pushType = String.valueOf(params.get("pushType"));
|
||||
}
|
||||
|
||||
@ -126,7 +130,7 @@ public class MessageEventListener {
|
||||
}
|
||||
} else {
|
||||
// 默认为单用户推送
|
||||
TencentIMServiceImpl.TencentIMResult imResult = tencentIMService.sendMessageToTencentIM(fromUserId, toUserId, content);
|
||||
TencentIMServiceImpl.TencentIMResult imResult = tencentIMService.sendMessageToTencentIM(fromUserId, toUserId, content,ext);
|
||||
tencentIMSendSuccess = imResult.isSuccess();
|
||||
if (tencentIMSendSuccess) {
|
||||
log.info("腾讯IM推送成功,userId={}, response={}", toUserId, imResult.getRawResponse());
|
||||
|
@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.system.domain.SysMessage;
|
||||
import org.dromara.system.domain.SysMessageTemplate;
|
||||
import org.dromara.system.domain.bo.SysMessageBo;
|
||||
import org.dromara.system.domain.vo.SysMessageVo;
|
||||
|
||||
@ -58,16 +59,17 @@ public interface ISysMessageService extends IService<SysMessage> {
|
||||
* @param userIds 用户ID列表 (String类型)
|
||||
* @return 结果
|
||||
*/
|
||||
int sendMessageToUsers(SysMessageBo message, List<String> userIds);
|
||||
int sendMessageToUsers(SysMessage message, SysMessageTemplate template,List<String> userIds);
|
||||
|
||||
/**
|
||||
* 发送自动消息
|
||||
*
|
||||
* @param message 消息信息
|
||||
* @param userIds 用户ID列表
|
||||
* @return 结果
|
||||
*/
|
||||
int sendAutoMessage(SysMessageBo message, List<Long> userIds);
|
||||
// /**
|
||||
// *
|
||||
// * 发送自动消息
|
||||
// *
|
||||
// * @param message 消息信息
|
||||
// * @param userIds 用户ID列表
|
||||
// * @return 结果
|
||||
// */
|
||||
// int sendAutoMessage(SysMessageBo message, List<Long> userIds);
|
||||
|
||||
/**
|
||||
* 标记消息为已读
|
||||
@ -173,4 +175,11 @@ public interface ISysMessageService extends IService<SysMessage> {
|
||||
*/
|
||||
SysMessage selectEntityById(Long id);
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
* @param bo
|
||||
* @return
|
||||
*/
|
||||
boolean send(SysMessageBo bo);
|
||||
|
||||
}
|
||||
|
@ -41,21 +41,6 @@ public interface ISysMessageTemplateService extends IService<SysMessageTemplate>
|
||||
*/
|
||||
SysMessageTemplateVo selectTemplateById(Long id);
|
||||
|
||||
/**
|
||||
* 新增消息模板
|
||||
*
|
||||
* @param template 消息模板信息
|
||||
* @return 结果
|
||||
*/
|
||||
int insertTemplate(SysMessageTemplateBo template);
|
||||
|
||||
/**
|
||||
* 修改消息模板
|
||||
*
|
||||
* @param template 消息模板信息
|
||||
* @return 结果
|
||||
*/
|
||||
int updateTemplate(SysMessageTemplateBo template);
|
||||
|
||||
/**
|
||||
* 批量删除消息模板
|
||||
@ -72,7 +57,7 @@ public interface ISysMessageTemplateService extends IService<SysMessageTemplate>
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteTemplateById(Long id);
|
||||
|
||||
|
||||
/**
|
||||
* 根据名称查询消息模板列表(不分页)
|
||||
*
|
||||
@ -80,4 +65,5 @@ public interface ISysMessageTemplateService extends IService<SysMessageTemplate>
|
||||
* @return 消息模板列表
|
||||
*/
|
||||
List<SysMessageTemplateVo> selectTemplateListByName(String name);
|
||||
SysMessageTemplate selectByTemplateType(String templateType) ;
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
package org.dromara.system.service;
|
||||
|
||||
import org.dromara.system.domain.bo.SysMessageBo;
|
||||
|
||||
public interface ISystemMessageUserService {
|
||||
}
|
@ -19,8 +19,7 @@ public interface ITencentIMService {
|
||||
* @param content 消息内容
|
||||
* @return 是否发送成功
|
||||
*/
|
||||
TencentIMServiceImpl.TencentIMResult sendMessageToTencentIM(String fromUserId, String toUserId, String content);
|
||||
|
||||
TencentIMServiceImpl.TencentIMResult sendMessageToTencentIM(String fromUserId, String toUserId, String content, String cloudCustomData);
|
||||
|
||||
/**
|
||||
* 推送消息给全体用户
|
||||
|
@ -4,23 +4,35 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
|
||||
import com.wzj.soopin.content.domain.po.Vlog;
|
||||
import com.wzj.soopin.content.service.VlogService;
|
||||
import com.wzj.soopin.member.domain.po.Member;
|
||||
import com.wzj.soopin.member.service.IMemberService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.commons.text.StringSubstitutor;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.im.enums.MessageActionEnum;
|
||||
import org.dromara.system.converter.SysMessageConvert;
|
||||
import org.dromara.system.converter.SysMessageTemplateConvert;
|
||||
import org.dromara.system.domain.SysMessage;
|
||||
import org.dromara.system.domain.SysMessageTemplate;
|
||||
import org.dromara.system.domain.SysMessageUser;
|
||||
import org.dromara.system.domain.bo.SysMessageBo;
|
||||
import org.dromara.system.domain.event.MessageEvent;
|
||||
import org.dromara.system.domain.vo.SysMessageVo;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
import org.dromara.system.mapper.SysMessageMapper;
|
||||
import org.dromara.system.mapper.SysMessageUserMapper;
|
||||
import org.dromara.system.service.ISysMessageService;
|
||||
import org.dromara.system.service.ISysMessageTemplateService;
|
||||
import org.dromara.system.service.ISysTenantService;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -41,8 +53,13 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
private final SysMessageMapper messageMapper;
|
||||
private final SysMessageUserMapper messageUserMapper;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
private final SysMessageTemplateServiceImpl messageTemplateService;
|
||||
|
||||
private final ISysUserService userService;
|
||||
private final ISysMessageTemplateService templateService;
|
||||
private final SysMessageConvert messageConvert;
|
||||
private final SysMessageTemplateConvert templateConvert;
|
||||
private final IMemberService memberService;
|
||||
private final ISysTenantService sysTenantService;
|
||||
private final VlogService vlogService;
|
||||
|
||||
@Override
|
||||
public TableDataInfo<SysMessageVo> selectPageMessageList(SysMessageBo bo, PageQuery pageQuery) {
|
||||
@ -89,26 +106,26 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
public int sendMessageToUser(SysMessageBo message, Long userId) {
|
||||
// 新增:通过模板类型编号查找并渲染模板(轻量变量替换)
|
||||
if (StringUtils.isNotBlank(message.getTemplateType())) {
|
||||
SysMessageTemplate template = messageTemplateService.selectByTemplateType(message.getTemplateType());
|
||||
SysMessageTemplate template = templateService.selectByTemplateType(message.getTemplateType());
|
||||
if (template == null) {
|
||||
throw new RuntimeException("消息模板不存在,templateType=" + message.getTemplateType());
|
||||
}
|
||||
Map<String, Object> params = message.getTemplateParams();
|
||||
String content = StringSubstitutor.replace(template.getTemplateContent(), params == null ? new java.util.HashMap<>() : params);
|
||||
String content = StringSubstitutor.replace(template.getContent(), params == null ? new java.util.HashMap<>() : params);
|
||||
message.setContent(content);
|
||||
}
|
||||
|
||||
|
||||
//加一个约定
|
||||
// 保存消息
|
||||
SysMessage entity = message.toEntity();
|
||||
SysMessage entity = messageConvert.toPo(message);
|
||||
Date scheduledTime = entity.getScheduledTime();
|
||||
entity.setStatus("1"); // 已发送
|
||||
messageMapper.insert(entity);
|
||||
// 检查消息与用户关联是否已存在
|
||||
LambdaQueryWrapper<SysMessageUser> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysMessageUser::getMessageId, entity.getId())
|
||||
.eq(SysMessageUser::getUserId, userId);
|
||||
.eq(SysMessageUser::getUserId, userId);
|
||||
int count = Math.toIntExact(messageUserMapper.selectCount(queryWrapper));
|
||||
int rows = 0;
|
||||
if (count == 0) {
|
||||
@ -132,13 +149,12 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int sendMessageToUsers(SysMessageBo message, List<String> userIds) {
|
||||
public int sendMessageToUsers(SysMessage message, SysMessageTemplate template, List<String> userIds) {
|
||||
if (userIds == null || userIds.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
// 保存消息
|
||||
SysMessage entity = message.toEntity();
|
||||
Date scheduledTime = entity.getScheduledTime();
|
||||
Date scheduledTime = message.getScheduledTime();
|
||||
// if (scheduledTime != null && scheduledTime.after(new Date())) {
|
||||
// entity.setStatus("0"); // 未发送
|
||||
// messageMapper.insert(entity);
|
||||
@ -191,8 +207,7 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
// // 定时消息不发布事件
|
||||
// return count;
|
||||
// } else {
|
||||
entity.setStatus("1"); // 已发送
|
||||
messageMapper.insert(entity);
|
||||
|
||||
// 批量创建消息用户关联
|
||||
int count = 0;
|
||||
List<Long> validUserIds = new ArrayList<>();
|
||||
@ -211,7 +226,7 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
}
|
||||
if (!validUserIds.isEmpty()) {
|
||||
LambdaQueryWrapper<SysMessageUser> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysMessageUser::getMessageId, entity.getId())
|
||||
queryWrapper.eq(SysMessageUser::getMessageId, message.getId())
|
||||
.in(SysMessageUser::getUserId, validUserIds);
|
||||
List<SysMessageUser> existingRecords = messageUserMapper.selectList(queryWrapper);
|
||||
Set<Long> existingUserIds = existingRecords.stream()
|
||||
@ -222,7 +237,7 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
if (!existingUserIds.contains(userId)) {
|
||||
try {
|
||||
SysMessageUser messageUser = new SysMessageUser();
|
||||
messageUser.setMessageId(entity.getId());
|
||||
messageUser.setMessageId(message.getId());
|
||||
messageUser.setUserId(userId);
|
||||
messageUser.setIsRead(false);
|
||||
int rows = messageUserMapper.insert(messageUser);
|
||||
@ -231,18 +246,25 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("创建消息用户关联失败: messageId={}, userId={}, error={}",
|
||||
entity.getId(), userId, e.getMessage());
|
||||
message.getId(), userId, e.getMessage());
|
||||
}
|
||||
} else {
|
||||
log.info("消息与用户关联已存在,跳过创建: messageId={}, userId={}", entity.getId(), userId);
|
||||
log.info("消息与用户关联已存在,跳过创建: messageId={}, userId={}", message.getId(), userId);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 最后只发送一次批量事件通知
|
||||
if (count > 0) {
|
||||
SysMessageVo messageVo = MapstructUtils.convert(entity, SysMessageVo.class);
|
||||
|
||||
SysMessageVo messageVo = MapstructUtils.convert(message, SysMessageVo.class);
|
||||
//获取模板信息,将模板的content作为参数传给消息
|
||||
messageVo.setTemplate(templateConvert.toVO(template));
|
||||
for (Long userId : validUserIds) {
|
||||
|
||||
messageVo.setContent(buildContent(template.getContent(), messageVo.getParams()));
|
||||
messageVo.setExt(buildContent(template.getExt(), messageVo.getParams()));
|
||||
|
||||
eventPublisher.publishEvent(new MessageEvent(this, messageVo, userId));
|
||||
}
|
||||
}
|
||||
@ -250,12 +272,12 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int sendAutoMessage(SysMessageBo message, List<Long> userIds) {
|
||||
message.setMsgType("AUTO");
|
||||
return sendMessageToUsers(message, userIds.stream().map(String::valueOf).collect(Collectors.toList()));
|
||||
}
|
||||
// @Override
|
||||
// @Transactional(rollbackFor = Exception.class)
|
||||
// public int sendAutoMessage(SysMessageBo message, List<Long> userIds) {
|
||||
// message.setMsgType("AUTO");
|
||||
// return sendMessageToUsers(message, userIds.stream().map(String::valueOf).collect(Collectors.toList()));
|
||||
// }
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@ -295,8 +317,6 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
LambdaQueryWrapper<SysMessage> lqw = new LambdaQueryWrapper<>();
|
||||
lqw.eq(StringUtils.isNotBlank(message.getMsgType()), SysMessage::getMsgType, message.getMsgType())
|
||||
.eq(StringUtils.isNotBlank(message.getSubType()), SysMessage::getSubType, message.getSubType())
|
||||
.eq(message.getSenderId() != null, SysMessage::getSenderId, message.getSenderId())
|
||||
// .eq(StringUtils.isNotBlank(message.getStatus()), SysMessage::getStatus, message.getStatus())
|
||||
.orderByDesc(SysMessage::getCreateTime);
|
||||
return MapstructUtils.convert(messageMapper.selectList(lqw), SysMessageVo.class);
|
||||
}
|
||||
@ -308,12 +328,12 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
|
||||
@Override
|
||||
public int insertMessage(SysMessageBo message) {
|
||||
return messageMapper.insert(message.toEntity());
|
||||
return messageMapper.insert(messageConvert.toPo(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateMessage(SysMessageBo message) {
|
||||
return messageMapper.updateById(message.toEntity());
|
||||
return messageMapper.updateById(messageConvert.toPo(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -350,7 +370,7 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
|
||||
// 尝试以字符串形式发送
|
||||
// 保存消息
|
||||
SysMessage entity = message.toEntity();
|
||||
SysMessage entity = messageConvert.toPo(message);
|
||||
messageMapper.insert(entity);
|
||||
|
||||
// 发送事件通知
|
||||
@ -382,4 +402,121 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
|
||||
return messageMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean send(SysMessageBo bo) {
|
||||
SysMessageTemplate template = templateService.getById(bo.getTemplateId());
|
||||
if (template != null) {
|
||||
// 使用模板的标题和内容
|
||||
bo.setTemplate(template);
|
||||
} else {
|
||||
throw new ServiceException("未找到指定的消息模板");
|
||||
}
|
||||
|
||||
// 验证发送范围是否为空
|
||||
Integer sendScope = bo.getSendScope();
|
||||
if (sendScope == null) {
|
||||
throw new ServiceException("发送范围不能为空");
|
||||
}
|
||||
|
||||
// 处理接收者
|
||||
List<String> idList = new ArrayList<>();
|
||||
|
||||
switch (sendScope) {
|
||||
case 1: // all
|
||||
idList = processAllIds(bo.getIdList());
|
||||
|
||||
break;
|
||||
case 2: // 指定用户
|
||||
idList = processUserIds(bo.getIdList());
|
||||
break;
|
||||
case 3: // 指定会员
|
||||
idList = processMemberIds(bo.getIdList());
|
||||
break;
|
||||
case 4: // 指定租户
|
||||
idList = processTenantIds(bo.getIdList());
|
||||
break;
|
||||
default:
|
||||
throw new ServiceException("不支持的消息类型");
|
||||
}
|
||||
|
||||
// 如果没有找到接收者,返回失败
|
||||
if (idList.isEmpty()) {
|
||||
throw new ServiceException("未找到消息接收者");
|
||||
}
|
||||
|
||||
//构建发送者
|
||||
MessageActionEnum actionEnum = MessageActionEnum.getByCode(template.getAction());
|
||||
//根据用户名获取发送者
|
||||
bo.setSenderId(actionEnum.name());
|
||||
|
||||
SysMessage message = messageConvert.toPo(bo);
|
||||
message.setStatus("1"); // 已发送
|
||||
message.setTitle(template.getTitle());
|
||||
message.setContent(template.getContent());
|
||||
message.setSendScope(sendScope);
|
||||
message.setTemplateId(template.getId());
|
||||
|
||||
//构建content
|
||||
|
||||
|
||||
//获取模板信息
|
||||
messageMapper.insert(message);
|
||||
|
||||
// 判断是否为定时消息,若是则注册SnailJob单次任务
|
||||
if (bo.getScheduledTime() != null && bo.getScheduledTime().after(new java.util.Date())) {
|
||||
|
||||
registSnailJob(bo, idList);
|
||||
} else {
|
||||
//推送消息
|
||||
sendMessageToUsers(message, template, idList);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private String buildContent(String orgMsg, Map<String, Object> params) {
|
||||
for (String key : params.keySet()) {
|
||||
orgMsg = orgMsg.replaceAll("\\$\\{" + key + "\\}", params.get(key).toString());
|
||||
}
|
||||
return orgMsg;
|
||||
}
|
||||
|
||||
private List<String> processAllIds(List<Long> idList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<String> processUserIds(List<Long> idList) {
|
||||
// 角色ID列表转换为用户ID列表
|
||||
return idList.stream().map(String::valueOf).toList();
|
||||
}
|
||||
|
||||
private List<String> processMemberIds(List<Long> idList) {
|
||||
// 会员ID列表转换为用户ID列表
|
||||
return idList.stream().map(String::valueOf).toList();
|
||||
|
||||
}
|
||||
|
||||
private List<String> processTenantIds(List<Long> idList) {
|
||||
// 租户ID列表转换为用户ID列表
|
||||
|
||||
List<SysUserVo> users = userService.selectUserByIds(idList, null);
|
||||
return users.stream().map(SysUserVo::getUserId).map(String::valueOf).toList();
|
||||
}
|
||||
|
||||
private boolean registSnailJob(SysMessageBo bo, List<String> idList) {
|
||||
// 先保存消息,获取ID
|
||||
// 创建SnailJob单次任务
|
||||
// SnailJobApiUtil.createSingleJob(null, bo.getScheduledTime());
|
||||
// // 关联用户
|
||||
// for (String userId : idList) {
|
||||
// org.dromara.system.domain.SysMessageUser messageUser = new org.dromara.system.domain.SysMessageUser();
|
||||
// messageUser.setMessageId(bo.getId());
|
||||
// messageUser.setUserId(Long.valueOf(userId));
|
||||
// messageUser.setIsRead(false);
|
||||
// // 这里假设有messageUserMapper可用,实际应通过service或mapper注入
|
||||
// // messageUserMapper.insert(messageUser);
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -31,12 +31,6 @@ public class SysMessageTemplateServiceImpl extends ServiceImpl<SysMessageTemplat
|
||||
@Override
|
||||
public TableDataInfo<SysMessageTemplateVo> selectTemplatePage(SysMessageTemplateBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<SysMessageTemplate> lqw = new LambdaQueryWrapper<>();
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getTemplateType()), SysMessageTemplate::getTemplateType, bo.getTemplateType())
|
||||
// .eq(StringUtils.isNotBlank(bo.getStatus()), SysMessageTemplate::getStatus, bo.getStatus())
|
||||
.like(StringUtils.isNotBlank(bo.getTemplateName()), SysMessageTemplate::getTemplateName, bo.getTemplateName())
|
||||
// .like(StringUtils.isNotBlank(bo.getTemplateCode()), SysMessageTemplate::getTemplateCode, bo.getTemplateCode())
|
||||
.orderByDesc(SysMessageTemplate::getCreateTime);
|
||||
|
||||
Page<SysMessageTemplate> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
|
||||
Page<SysMessageTemplate> resultPage = templateMapper.selectPage(page, lqw);
|
||||
List<SysMessageTemplateVo> records = MapstructUtils.convert(resultPage.getRecords(), SysMessageTemplateVo.class);
|
||||
@ -47,13 +41,7 @@ public class SysMessageTemplateServiceImpl extends ServiceImpl<SysMessageTemplat
|
||||
|
||||
@Override
|
||||
public List<SysMessageTemplateVo> selectTemplateList(SysMessageTemplateBo bo) {
|
||||
LambdaQueryWrapper<SysMessageTemplate> lqw = new LambdaQueryWrapper<>();
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getTemplateType()), SysMessageTemplate::getTemplateType, bo.getTemplateType())
|
||||
// .eq(StringUtils.isNotBlank(bo.getStatus()), SysMessageTemplate::getStatus, bo.getStatus())
|
||||
.like(StringUtils.isNotBlank(bo.getTemplateName()), SysMessageTemplate::getTemplateName, bo.getTemplateName())
|
||||
// .like(StringUtils.isNotBlank(bo.getTemplateCode()), SysMessageTemplate::getTemplateCode, bo.getTemplateCode())
|
||||
.orderByDesc(SysMessageTemplate::getCreateTime);
|
||||
return MapstructUtils.convert(templateMapper.selectList(lqw), SysMessageTemplateVo.class);
|
||||
return MapstructUtils.convert(templateMapper.selectList(bo.toWrapper()), SysMessageTemplateVo.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -61,16 +49,6 @@ public class SysMessageTemplateServiceImpl extends ServiceImpl<SysMessageTemplat
|
||||
return MapstructUtils.convert(templateMapper.selectById(id), SysMessageTemplateVo.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertTemplate(SysMessageTemplateBo bo) {
|
||||
return templateMapper.insert(bo.toEntity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateTemplate(SysMessageTemplateBo bo) {
|
||||
return templateMapper.updateById(bo.toEntity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteTemplateByIds(Long[] ids) {
|
||||
return templateMapper.deleteBatchIds(List.of(ids));
|
||||
@ -80,12 +58,12 @@ public class SysMessageTemplateServiceImpl extends ServiceImpl<SysMessageTemplat
|
||||
public int deleteTemplateById(Long id) {
|
||||
return templateMapper.deleteById(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<SysMessageTemplateVo> selectTemplateListByName(String name) {
|
||||
LambdaQueryWrapper<SysMessageTemplate> queryWrapper = new LambdaQueryWrapper<>();
|
||||
if (StringUtils.isNotBlank(name)) {
|
||||
queryWrapper.like(SysMessageTemplate::getTemplateName, name);
|
||||
queryWrapper.like(SysMessageTemplate::getName, name);
|
||||
}
|
||||
queryWrapper.orderByDesc(SysMessageTemplate::getCreateTime);
|
||||
return MapstructUtils.convert(templateMapper.selectList(queryWrapper), SysMessageTemplateVo.class);
|
||||
@ -94,9 +72,10 @@ public class SysMessageTemplateServiceImpl extends ServiceImpl<SysMessageTemplat
|
||||
/**
|
||||
* 根据模板类型编号查找模板
|
||||
*/
|
||||
@Override
|
||||
public SysMessageTemplate selectByTemplateType(String templateType) {
|
||||
LambdaQueryWrapper<SysMessageTemplate> lqw = new LambdaQueryWrapper<>();
|
||||
lqw.eq(SysMessageTemplate::getTemplateType, templateType).eq(SysMessageTemplate::getStatus, 0);
|
||||
lqw.eq(SysMessageTemplate::getType, templateType).eq(SysMessageTemplate::getStatus, 0);
|
||||
return templateMapper.selectOne(lqw);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package org.dromara.system.service.impl;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.system.domain.SysMessageTemplate;
|
||||
import org.dromara.system.domain.bo.SysMessageBo;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
import org.dromara.system.service.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class SystemMessageUserService implements ISystemMessageUserService {
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package org.dromara.system.service.impl;
|
||||
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -170,7 +171,7 @@ public class TencentIMServiceImpl implements ITencentIMService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TencentIMResult sendMessageToTencentIM(String fromUserId, String toUserId, String content) {
|
||||
public TencentIMResult sendMessageToTencentIM(String fromUserId, String toUserId, String msgBody,String cloudCustomData) {
|
||||
TencentIMResult result = new TencentIMResult();
|
||||
try {
|
||||
String userSig = generateAdminUserSig();
|
||||
@ -182,17 +183,16 @@ public class TencentIMServiceImpl implements ITencentIMService {
|
||||
adminAccount,
|
||||
userSig,
|
||||
random);
|
||||
Map<String, Object> msgContent = new HashMap<>();
|
||||
msgContent.put("Text", content);
|
||||
Map<String, Object> msgBody = new HashMap<>();
|
||||
msgBody.put("MsgType", "TIMTextElem");
|
||||
msgBody.put("MsgContent", msgContent);
|
||||
Map<String, Object> requestBody = new HashMap<>();
|
||||
|
||||
JSONArray jsonArray=new JSONArray();
|
||||
jsonArray.add(new JSONObject(msgBody));
|
||||
JSONObject requestBody = new JSONObject();
|
||||
requestBody.put("SyncOtherMachine", 2);
|
||||
requestBody.put("From_Account", fromUserId);
|
||||
requestBody.put("To_Account", toUserId);
|
||||
requestBody.put("MsgRandom", Integer.parseInt(random));
|
||||
requestBody.put("MsgBody", new Object[]{msgBody});
|
||||
requestBody.put("MsgBody", jsonArray);
|
||||
requestBody.put("CloudCustomData", cloudCustomData);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
|
||||
@ -248,6 +248,7 @@ public class TencentIMServiceImpl implements ITencentIMService {
|
||||
requestBody.put("MsgRandom", Integer.parseInt(random));
|
||||
requestBody.put("MsgBody", new Object[]{msgBody});
|
||||
|
||||
requestBody.put("CloudCustomData", ext);
|
||||
// 设置离线推送信息
|
||||
if (offlinePush) {
|
||||
Map<String, Object> offlinePushInfo = new HashMap<>();
|
||||
|
@ -34,10 +34,7 @@
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-translation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-im</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- OSS功能模块 -->
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
|
@ -124,7 +124,7 @@ public class FansController {
|
||||
log.warn("IM回调Pair参数转换失败: {}", pair);
|
||||
continue;
|
||||
}
|
||||
handleImFollow(fromId, java.util.Arrays.asList(toId));
|
||||
service.doFollow(fromId, toId);
|
||||
log.info("IM回调处理成功: fromId={}, vloggerId={}", fromId, toId);
|
||||
} else {
|
||||
log.warn("IM回调Pair参数不完整: {}", pair);
|
||||
|
@ -25,7 +25,6 @@ public class ImCallbackController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ImCallbackController.class);
|
||||
// private static final String CALLBACK_TOKEN = "your_auth_token"; //
|
||||
|
||||
@Autowired
|
||||
private IMemberService memberService;
|
||||
@Autowired
|
||||
@ -37,10 +36,10 @@ public class ImCallbackController {
|
||||
|
||||
@PostMapping
|
||||
public R handleCallback(
|
||||
@RequestParam(value = "Sign", required = false) String sign,
|
||||
@RequestParam(value = "RequestTime", required = false) String requestTime,
|
||||
@RequestParam(value = "CallbackCommand", required = false) String callbackCommand,
|
||||
@RequestBody Map<String, Object> requestBody) {
|
||||
@RequestParam(value = "Sign", required = false) String sign,
|
||||
@RequestParam(value = "RequestTime", required = false) String requestTime,
|
||||
@RequestParam(value = "CallbackCommand", required = false) String callbackCommand,
|
||||
@RequestBody Map<String, Object> requestBody) {
|
||||
|
||||
// // 1. 签名验证
|
||||
// if (!verifySignature(CALLBACK_TOKEN, sign, requestTime)) {
|
||||
@ -55,11 +54,11 @@ public class ImCallbackController {
|
||||
return R.fail(1002, "缺少CallbackCommand");
|
||||
}
|
||||
switch (callbackCommand) {
|
||||
case "Sns.CallbackFriendAdd":
|
||||
case "Sns.CallbackFriendAdd"://好友添加
|
||||
// 关注,直接调用 FansController 的 follow
|
||||
fansController.follow(requestBody, null, null);
|
||||
break;
|
||||
case "Sns.CallbackFriendDelete":
|
||||
case "Sns.CallbackFriendDelete"://好友删除
|
||||
// 取关,直接调用 FansController 的 cancel
|
||||
fansController.cancel(requestBody, null, null);
|
||||
break;
|
||||
@ -73,6 +72,12 @@ public class ImCallbackController {
|
||||
case "Sns.CallbackBlackListDelete":
|
||||
handleImCancelBlock(requestBody);
|
||||
break;
|
||||
case "Follow.CallbackAfterFollowAdd"://关注
|
||||
fansController.follow(requestBody, null, null);
|
||||
break;
|
||||
case "Follow.CallbackAfterFollowDelete"://取关
|
||||
fansController.cancel(requestBody, null, null);
|
||||
break;
|
||||
default:
|
||||
log.info("收到未知事件类型: {}, 参数: {}", callbackCommand, requestBody);
|
||||
break;
|
||||
@ -81,7 +86,7 @@ public class ImCallbackController {
|
||||
}
|
||||
|
||||
// 处理IM关注事件
|
||||
private void handleImFollow(Map<String, Object>requestBody) {
|
||||
private void handleImFollow(Map<String, Object> requestBody) {
|
||||
Object pairListObj = requestBody.get("PairList");
|
||||
if (pairListObj instanceof List) {
|
||||
List<?> pairList = (List<?>) pairListObj;
|
||||
|
@ -7,7 +7,6 @@ import com.wzj.soopin.member.convert.MemberAddressConvert;
|
||||
import com.wzj.soopin.member.domain.bo.MemberAddressBO;
|
||||
import com.wzj.soopin.member.domain.po.MemberAddress;
|
||||
import com.wzj.soopin.member.domain.vo.MemberAddressVO;
|
||||
import org.dromara.system.mapper.AddressMapper;
|
||||
import com.wzj.soopin.member.service.IMemberAddressService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -15,10 +14,9 @@ import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.redis.redis.RedisService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 会员收货地址Controller
|
||||
|
@ -64,7 +64,7 @@ public class MemberController extends BaseController {
|
||||
@Tag(name ="获取会员信息详细信息")
|
||||
@GetMapping(value = "{id}")
|
||||
public R<MemberVO> getInfo(@PathVariable("id") Long id) {
|
||||
return R.ok(convert.toVO(service.getById(id)));
|
||||
return R.ok(service.getMemberInfo(id));
|
||||
}
|
||||
|
||||
@Tag(name ="新增会员信息")
|
||||
|
@ -5,25 +5,20 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.wzj.soopin.member.domain.po.Fans;
|
||||
import com.wzj.soopin.member.domain.po.Member;
|
||||
import com.wzj.soopin.member.domain.vo.FansVO;
|
||||
import com.wzj.soopin.member.mapper.FansMapper;
|
||||
import com.wzj.soopin.member.service.IFansService;
|
||||
import com.wzj.soopin.member.service.IMemberService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.constant.CacheConstants;
|
||||
import org.dromara.common.core.enums.YesOrNo;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.redis.config.RedisConfig;
|
||||
import org.dromara.common.redis.redis.RedisCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.dromara.system.service.ISysMessageService;
|
||||
import org.dromara.system.service.ISysMessageTemplateService;
|
||||
import org.dromara.system.domain.bo.SysMessageBo;
|
||||
import org.dromara.system.domain.vo.SysMessageTemplateVo;
|
||||
import com.wzj.soopin.member.domain.po.Member;
|
||||
import com.wzj.soopin.member.service.IMemberService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -35,10 +30,7 @@ public class FansServiceImpl extends ServiceImpl<FansMapper, Fans> implements IF
|
||||
|
||||
|
||||
private final RedisCache redisCache;
|
||||
@Autowired
|
||||
private ISysMessageService sysMessageService;
|
||||
@Autowired
|
||||
private ISysMessageTemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private IMemberService memberService;
|
||||
|
||||
@ -72,17 +64,17 @@ public class FansServiceImpl extends ServiceImpl<FansMapper, Fans> implements IF
|
||||
Member vlogger = memberService.getById(vloggerId);
|
||||
if (follower != null && vlogger != null && !myId.equals(vloggerId)) {
|
||||
// 新版:使用模板类型编号和参数
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("followerNickname", follower.getNickname() == null ? "" : follower.getNickname());
|
||||
params.put("vloggerNickname", vlogger.getNickname() == null ? "" : vlogger.getNickname());
|
||||
SysMessageBo messageBo = new SysMessageBo();
|
||||
// 关注类型编号
|
||||
messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.FOLLOW);
|
||||
messageBo.setTemplateParams(params);
|
||||
messageBo.setSenderId(myId);
|
||||
// 补充:设置消息标题,防止title为null
|
||||
messageBo.setTitle("关注通知");
|
||||
sysMessageService.sendMessageToUser(messageBo, vloggerId);
|
||||
// Map<String, Object> params = new HashMap<>();
|
||||
// params.put("followerNickname", follower.getNickname() == null ? "" : follower.getNickname());
|
||||
// params.put("vloggerNickname", vlogger.getNickname() == null ? "" : vlogger.getNickname());
|
||||
// SysMessageBo messageBo = new SysMessageBo();
|
||||
// // 关注类型编号
|
||||
// messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.FOLLOW);
|
||||
// messageBo.setTemplateParams(params);
|
||||
// messageBo.setSenderId(myId);
|
||||
// // 补充:设置消息标题,防止title为null
|
||||
// messageBo.setTitle("关注通知");
|
||||
// sysMessageService.sendMessageToUser(messageBo, vloggerId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,16 +114,16 @@ public class FansServiceImpl extends ServiceImpl<FansMapper, Fans> implements IF
|
||||
Member vlogger = memberService.getById(vloggerId);
|
||||
if (follower != null && vlogger != null && !myId.equals(vloggerId)) {
|
||||
// 新版:使用模板类型编号和参数
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("followerNickname", follower.getNickname() == null ? "" : follower.getNickname());
|
||||
params.put("vloggerNickname", vlogger.getNickname() == null ? "" : vlogger.getNickname());
|
||||
SysMessageBo messageBo = new SysMessageBo();
|
||||
messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.UNFOLLOW); // 取关类型编号
|
||||
messageBo.setTemplateParams(params);
|
||||
messageBo.setSenderId(myId);
|
||||
// 补充:设置消息标题,防止title为null
|
||||
messageBo.setTitle("取消关注通知");
|
||||
sysMessageService.sendMessageToUser(messageBo, vloggerId);
|
||||
// Map<String, Object> params = new HashMap<>();
|
||||
// params.put("followerNickname", follower.getNickname() == null ? "" : follower.getNickname());
|
||||
// params.put("vloggerNickname", vlogger.getNickname() == null ? "" : vlogger.getNickname());
|
||||
// SysMessageBo messageBo = new SysMessageBo();
|
||||
// messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.UNFOLLOW); // 取关类型编号
|
||||
// messageBo.setTemplateParams(params);
|
||||
// messageBo.setSenderId(myId);
|
||||
// // 补充:设置消息标题,防止title为null
|
||||
// messageBo.setTitle("取消关注通知");
|
||||
// sysMessageService.sendMessageToUser(messageBo, vloggerId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,7 +137,7 @@ public class FansServiceImpl extends ServiceImpl<FansMapper, Fans> implements IF
|
||||
public boolean queryDoIFollowVloger(String myId, String vloggerId) {
|
||||
try {
|
||||
// Try to convert string IDs to Long if they are numeric
|
||||
if (myId != null && vloggerId != null &&
|
||||
if (myId != null && vloggerId != null &&
|
||||
myId.matches("\\d+") && vloggerId.matches("\\d+")) {
|
||||
Fans vlogger = queryFansRelationship(Long.valueOf(myId), Long.valueOf(vloggerId));
|
||||
return vlogger != null;
|
||||
|
@ -20,6 +20,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.constant.CacheConstants;
|
||||
import org.dromara.common.core.constant.CachePrefix;
|
||||
import org.dromara.common.core.constant.GlobalConstants;
|
||||
import org.dromara.common.core.constant.ResultCode;
|
||||
import org.dromara.common.core.domain.model.LoginUser;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
@ -95,7 +96,7 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper,Member> implemen
|
||||
return true;
|
||||
}
|
||||
|
||||
@CacheEvict(value = CacheConstants.MEMBER, key = "#id")
|
||||
@CacheEvict(value = GlobalConstants.MEMBER_KEY, key = "#id")
|
||||
public int updateMark(MemberBO member) {
|
||||
UpdateWrapper<Member> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.set("mark",member.getMark())
|
||||
@ -106,7 +107,7 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper,Member> implemen
|
||||
|
||||
|
||||
|
||||
@CacheEvict(value = CacheConstants.MEMBER, key = "#id")
|
||||
@CacheEvict(value = GlobalConstants.MEMBER_KEY, key = "#id")
|
||||
public Integer changeStatus(MemberBO bo) {
|
||||
UpdateWrapper<Member> wrapper = new UpdateWrapper<>();
|
||||
wrapper.eq("id", bo.getId());
|
||||
@ -258,7 +259,7 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper,Member> implemen
|
||||
|
||||
|
||||
@Override
|
||||
@Cacheable (cacheNames = CacheConstants.MEMBER, key = "#id")
|
||||
@Cacheable (cacheNames = GlobalConstants.MEMBER_KEY , key = "#id")
|
||||
public MemberVO getMemberInfo(Serializable id) {
|
||||
return memberConvert.toVO(getById(id));
|
||||
}
|
||||
|
@ -162,10 +162,7 @@
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-content</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-im</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 微信支付V3 SDK -->
|
||||
<dependency>
|
||||
<groupId>com.github.wechatpay-apiv3</groupId>
|
||||
|
@ -79,7 +79,7 @@ public class OrderController extends BaseController {
|
||||
|
||||
if (result != null) {
|
||||
// 订单创建成功,发送消息
|
||||
service.sendMessage(order);
|
||||
// service.sendMessage(order);
|
||||
log.info("订单创建成功,消息已发送,订单ID: {}", order.getId());
|
||||
} else {
|
||||
log.warn("订单创建失败: {}", "返回结果为null");
|
||||
|
@ -1,17 +1,18 @@
|
||||
package com.wzj.soopin.order.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.wzj.soopin.goods.domain.entity.Sku;
|
||||
import com.wzj.soopin.goods.mapper.SkuMapper;
|
||||
import com.wzj.soopin.member.domain.po.Member;
|
||||
import com.wzj.soopin.member.mapper.*;
|
||||
import com.wzj.soopin.member.mapper.MemberMapper;
|
||||
import com.wzj.soopin.member.mapper.MemberWechatMapper;
|
||||
import com.wzj.soopin.order.domain.bo.OrderBo;
|
||||
import com.wzj.soopin.order.domain.entity.*;
|
||||
import com.wzj.soopin.order.domain.form.DeliverProductForm;
|
||||
@ -30,11 +31,7 @@ import org.dromara.common.core.utils.SecurityUtils;
|
||||
import org.dromara.common.redis.redis.RedisService;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.system.domain.SysTenant;
|
||||
import org.dromara.system.domain.bo.SysMessageBo;
|
||||
import org.dromara.system.domain.vo.SysMessageTemplateVo;
|
||||
import org.dromara.system.mapper.SysTenantMapper;
|
||||
import org.dromara.system.service.ISysMessageTemplateService;
|
||||
import org.dromara.system.service.impl.SysMessageServiceImpl;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
@ -63,8 +60,6 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
private final OrderDeliveryHistoryMapper orderDeliveryHistoryMapper;
|
||||
private final VerificationCodeService verificationCodeService;
|
||||
private final SysTenantMapper sysTenantMapper;
|
||||
private final ISysMessageTemplateService templateService;
|
||||
private final SysMessageServiceImpl sysMessageService;
|
||||
private final MemberWechatMapper memberWechatMapper;
|
||||
private final WechatPaymentHistoryMapper wechatPaymentHistoryMapper;
|
||||
private final RedisService redisService;
|
||||
@ -499,27 +494,27 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
return baseMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderSn,orderNo));
|
||||
}
|
||||
|
||||
public void sendMessage(Order order) {
|
||||
Long memberId = order.getMemberId();
|
||||
Long orderId = order.getId();
|
||||
// 订单创建成功模板ID
|
||||
Long templateId =1940586928850100226L;
|
||||
// 查询模板信息
|
||||
SysMessageTemplateVo template = templateService.selectTemplateById(templateId);
|
||||
log.info("模板信息为: {}", template);
|
||||
|
||||
if (template != null) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("orderSn", order.getOrderSn());
|
||||
params.put("productName", orderItemMapper.getName(orderId));
|
||||
SysMessageBo messageBo = new SysMessageBo();
|
||||
messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.ORDER_NOTICE);
|
||||
messageBo.setTemplateParams(params);
|
||||
messageBo.setSenderId(memberId);
|
||||
messageBo.setTitle(template.getTitle());
|
||||
sysMessageService.sendMessageToUser(messageBo, memberId);
|
||||
}
|
||||
}
|
||||
// public void sendMessage(Order order) {
|
||||
// Long memberId = order.getMemberId();
|
||||
// Long orderId = order.getId();
|
||||
// // 订单创建成功模板ID
|
||||
// Long templateId =1940586928850100226L;
|
||||
// // 查询模板信息
|
||||
// SysMessageTemplateVo template = templateService.selectTemplateById(templateId);
|
||||
// log.info("模板信息为: {}", template);
|
||||
//
|
||||
// if (template != null) {
|
||||
// Map<String, Object> params = new HashMap<>();
|
||||
// params.put("orderSn", order.getOrderSn());
|
||||
// params.put("productName", orderItemMapper.getName(orderId));
|
||||
// SysMessageBo messageBo = new SysMessageBo();
|
||||
// messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.ORDER_NOTICE);
|
||||
// messageBo.setTemplateParams(params);
|
||||
// messageBo.setSenderId(memberId);
|
||||
// messageBo.setTitle(template.getTitle());
|
||||
// sysMessageService.sendMessageToUser(messageBo, memberId);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 处理退款逻辑
|
||||
|
@ -15,10 +15,6 @@ import com.wzj.soopin.order.utils.StringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.system.domain.bo.SysMessageBo;
|
||||
import org.dromara.system.domain.vo.SysMessageTemplateVo;
|
||||
import org.dromara.system.service.ISysMessageTemplateService;
|
||||
import org.dromara.system.service.impl.SysMessageServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@ -40,8 +36,6 @@ public class VerificationCodeServiceImpl extends ServiceImpl<VerificationCodesM
|
||||
private final OrderMapper orderMapper;
|
||||
private final QrCodeGenerator qrCodeGenerator;
|
||||
private final VerificationLogsMapper logMapper;
|
||||
private final ISysMessageTemplateService templateService;
|
||||
private final SysMessageServiceImpl sysMessageService;
|
||||
|
||||
/**
|
||||
* 生成核销码并关联订单
|
||||
@ -231,14 +225,14 @@ public class VerificationCodeServiceImpl extends ServiceImpl<VerificationCodesM
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
// params.put("productName", productName);
|
||||
params.put("verificationTime", formattedTime);
|
||||
SysMessageBo messageBo = new SysMessageBo();
|
||||
// 核销成功类型编号
|
||||
messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.VERIFY_SUCCESS);
|
||||
messageBo.setTemplateParams(params);
|
||||
messageBo.setSenderId(memberId);
|
||||
// 补充:设置消息标题
|
||||
messageBo.setTitle("核销成功通知");
|
||||
sysMessageService.sendMessageToUser(messageBo, memberId);
|
||||
// SysMessageBo messageBo = new SysMessageBo();
|
||||
// // 核销成功类型编号
|
||||
// messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.VERIFY_SUCCESS);
|
||||
// messageBo.setTemplateParams(params);
|
||||
// messageBo.setSenderId(memberId);
|
||||
// // 补充:设置消息标题
|
||||
// messageBo.setTitle("核销成功通知");
|
||||
// sysMessageService.sendMessageToUser(messageBo, memberId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -253,13 +247,13 @@ public class VerificationCodeServiceImpl extends ServiceImpl<VerificationCodesM
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
// params.put("productName", productName);
|
||||
params.put("reason", reason);
|
||||
SysMessageBo messageBo = new SysMessageBo();
|
||||
// 核销失败类型编号
|
||||
messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.VERIFY_FAIL);
|
||||
messageBo.setTemplateParams(params);
|
||||
messageBo.setSenderId(memberId);
|
||||
// 补充:设置消息标题
|
||||
messageBo.setTitle("核销失败通知");
|
||||
sysMessageService.sendMessageToUser(messageBo, memberId);
|
||||
// SysMessageBo messageBo = new SysMessageBo();
|
||||
// // 核销失败类型编号
|
||||
// messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.VERIFY_FAIL);
|
||||
// messageBo.setTemplateParams(params);
|
||||
// messageBo.setSenderId(memberId);
|
||||
// // 补充:设置消息标题
|
||||
// messageBo.setTitle("核销失败通知");
|
||||
// sysMessageService.sendMessageToUser(messageBo, memberId);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user