[fix]修改bug

This commit is contained in:
wangqx 2025-08-25 14:35:44 +08:00
parent b450526775
commit c21d61f4f0
55 changed files with 1098 additions and 762 deletions

13
pom.xml
View File

@ -102,13 +102,6 @@
<!-- 依赖声明 --> <!-- 依赖声明 -->
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<!-- knife4j 接口文档工具 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.9</version>
</dependency>
<dependency> <dependency>
<groupId>com.github.xiaoymin</groupId> <groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-springdoc-ui</artifactId> <artifactId>knife4j-springdoc-ui</artifactId>
@ -411,7 +404,11 @@
<artifactId>ruoyi-goods</artifactId> <artifactId>ruoyi-goods</artifactId>
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-rabbitmq</artifactId>
<version>${revision}</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId> <artifactId>spring-boot-starter-amqp</artifactId>

View File

@ -79,7 +79,7 @@ public class AppMemberController {
if (loginUser == null) { if (loginUser == null) {
throw new ServiceException("用户未登录"); throw new ServiceException("用户未登录");
} }
return R.ok(convert.toVO(service.getById(loginUser.getUserId()))); return R.ok(service.getMemberInfo(loginUser.getUserId()));
} }
@Tag(name = "获取会员账户表详细信息") @Tag(name = "获取会员账户表详细信息")

View File

@ -65,7 +65,7 @@ public class AppOrderController {
if (result != null) { if (result != null) {
// 订单创建成功发送消息 // 订单创建成功发送消息
orderService.sendMessage(order); // orderService.sendMessage(order);
log.info("订单创建成功消息已发送订单ID: {}", order.getId()); log.info("订单创建成功消息已发送订单ID: {}", order.getId());
} else { } else {
log.warn("订单创建失败: {}", "返回结果为null"); log.warn("订单创建失败: {}", "返回结果为null");

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.wzj.soopin.content.domain.bo.*; import com.wzj.soopin.content.domain.bo.*;
import com.wzj.soopin.content.domain.po.MyLikedVlog; 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.domain.vo.IndexVlogVO;
import com.wzj.soopin.content.service.VlogService; import com.wzj.soopin.content.service.VlogService;
import com.wzj.soopin.content.service.VlogUploadService; import com.wzj.soopin.content.service.VlogUploadService;
@ -45,6 +46,16 @@ public class AppVlogController {
@Tag(name = "首页视频列表") @Tag(name = "首页视频列表")
@PostMapping("/indexList") @PostMapping("/indexList")
public R<Page<IndexVlogVO>> indexList(@RequestBody IndexListBO bo, @RequestBody Page page) { 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); Page<IndexVlogVO> pages = vlogService.getIndexVlogList(bo, page);
return R.ok(pages); return R.ok(pages);
} }
@ -100,6 +111,15 @@ public class AppVlogController {
} }
@PostMapping("publish") @PostMapping("publish")
public R<Void> publish(@RequestBody VlogBO vlogBO) throws Exception { 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(); String url = vlogBO.getUrl();
log.info("未审核视频地址:"+url); log.info("未审核视频地址:"+url);
String fileName = url.substring(url.lastIndexOf("/") + 1); String fileName = url.substring(url.lastIndexOf("/") + 1);
@ -137,18 +157,20 @@ public class AppVlogController {
} }
String userId = String.valueOf(loginUser.getUserId()); String userId = String.valueOf(loginUser.getUserId());
String vlogerId = params.get("vlogerId");
String vlogId = params.get("vlogId"); 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); vlogService.userLikeVlog(userId, vlogId);
// 点赞后视频和视频发布者的获赞都会 +1 // 点赞后视频和视频发布者的获赞都会 +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.increment(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
// 我点赞的视频需要在redis中保存关联关系 // 我点赞的视频需要在redis中保存关联关系
@ -179,17 +201,18 @@ public class AppVlogController {
} }
String userId = String.valueOf(loginUser.getUserId()); String userId = String.valueOf(loginUser.getUserId());
String vlogerId = params.get("vlogerId");
String vlogId = params.get("vlogId"); String vlogId = params.get("vlogId");
if (StringUtils.isBlank(vlogerId) || StringUtils.isBlank(vlogId)) { //获取vlog
throw new ServiceException("参数不完整"); Vlog vlog = vlogService.getVlog(vlogId);
if(vlog==null){
throw new ServiceException("视频不存在");
} }
// 我取消点赞的视频关联关系删除 // 我取消点赞的视频关联关系删除
vlogService.userUnLikeVlog(userId, vlogId); 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.decrement(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
redis.del(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId); redis.del(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId);

View File

@ -74,20 +74,28 @@ public class IndexServiceImpl implements IndexService {
private void addCompositeStatistics(Map<String, Object> result) { private void addCompositeStatistics(Map<String, Object> result) {
// 商品统计 // 商品统计
Map<String, Object> productCounts = productMapper.countProduct(); Map<String, Object> productCounts = productMapper.countProduct();
if(productCounts!=null){
result.put("productCount", productCounts.get("count2")); result.put("productCount", productCounts.get("count2"));
result.put("productAudit", productCounts.get("count1")); result.put("productAudit", productCounts.get("count1"));
}
// 店铺统计 // 店铺统计
Map<String, Object> storeCounts = sysTenantMapper.countProduct(); Map<String, Object> storeCounts = sysTenantMapper.countProduct();
if(storeCounts!=null){
result.put("storeCount", storeCounts.get("count1")); result.put("storeCount", storeCounts.get("count1"));
result.put("StoreAudit", storeCounts.get("count2")); result.put("StoreAudit", storeCounts.get("count2"));
}
// 订单统计 // 订单统计
Map<String, Object> orderCounts = orderMapper.countOrder(); Map<String, Object> orderCounts = orderMapper.countOrder();
if(orderCounts!=null){
result.put("orderCount", orderCounts.get("count1")); result.put("orderCount", orderCounts.get("count1"));
result.put("orderAudit", orderCounts.get("count2")); result.put("orderAudit", orderCounts.get("count2"));
} }
}
/** Top20排行榜 */ /** Top20排行榜 */
private void addTop20Statistics(Map<String, Object> result) { private void addTop20Statistics(Map<String, Object> result) {
result.put("top20Stores", sysTenantMapper.getTop20Stores()); result.put("top20Stores", sysTenantMapper.getTop20Stores());

View File

@ -31,4 +31,9 @@ public interface GlobalConstants {
* 三方认证 redis key * 三方认证 redis key
*/ */
String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:"; String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:";
/**
* 会员 redis key
*/
String MEMBER_KEY = GLOBAL_REDIS_KEY + "member:";
} }

View File

@ -8,7 +8,6 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-common-rabbitmq</artifactId> <artifactId>ruoyi-common-rabbitmq</artifactId>
<description> <description>
ruoyi-common-rabbitmq ruoyi-common-rabbitmq
</description> </description>
@ -28,6 +27,13 @@
<artifactId>spring-boot-starter-amqp</artifactId> <artifactId>spring-boot-starter-amqp</artifactId>
</dependency> </dependency>
<!-- Jackson for JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
package org.dromara.common.redis.config.properties; package org.dromara.common.rabbitmq.config.properties;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;

View File

@ -10,7 +10,7 @@ import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.SpringUtils; 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.KeyPrefixHandler;
import org.dromara.common.redis.handler.RedisExceptionHandler; import org.dromara.common.redis.handler.RedisExceptionHandler;
import org.redisson.client.codec.StringCodec; import org.redisson.client.codec.StringCodec;

View File

@ -96,6 +96,7 @@ public class PlusSpringCacheManager implements CacheManager {
if (names != null) { if (names != null) {
for (String name : names) { for (String name : names) {
getCache(name); getCache(name);
} }
dynamic = false; dynamic = false;
} else { } else {

View File

@ -5,7 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import org.dromara.common.core.utils.reflect.ReflectUtils; import org.dromara.common.core.utils.reflect.ReflectUtils;
import org.dromara.common.redis.config.RedisConfig; 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.core.TenantSaTokenDao;
import org.dromara.common.tenant.handle.PlusTenantLineHandler; import org.dromara.common.tenant.handle.PlusTenantLineHandler;
import org.dromara.common.tenant.handle.TenantKeyPrefixHandler; import org.dromara.common.tenant.handle.TenantKeyPrefixHandler;

View File

@ -144,12 +144,7 @@
<groupId>org.dromara</groupId> <groupId>org.dromara</groupId>
<artifactId>ruoyi-member</artifactId> <artifactId>ruoyi-member</artifactId>
</dependency> </dependency>
<!-- <dependency>-->
<!-- <groupId>com.github.pagehelper</groupId>-->
<!-- <artifactId>pagehelper</artifactId>-->
<!-- <version>5.3.2</version>-->
<!-- <scope>compile</scope>-->
<!-- </dependency>-->
<dependency> <dependency>
<groupId>com.squareup.okhttp3</groupId> <groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId> <artifactId>okhttp</artifactId>
@ -161,12 +156,7 @@
<artifactId>spring-rabbit</artifactId> <artifactId>spring-rabbit</artifactId>
</dependency> </dependency>
<!-- 腾讯云视频点播SDK -->
<!-- <dependency>-->
<!-- <groupId>com.tencentcloudapi</groupId>-->
<!-- <artifactId>tencentcloud-sdk-java-vod</artifactId>-->
<!-- <version>3.1.1030</version>-->
<!-- </dependency>-->
<!-- 腾讯云SDK公共模块 --> <!-- 腾讯云SDK公共模块 -->
<dependency> <dependency>
@ -178,10 +168,7 @@
<groupId>org.dromara</groupId> <groupId>org.dromara</groupId>
<artifactId>ruoyi-system</artifactId> <artifactId>ruoyi-system</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-im</artifactId>
</dependency>
<!-- 腾讯云SDK核心模块 --> <!-- 腾讯云SDK核心模块 -->
<!-- <dependency>--> <!-- <dependency>-->
<!-- <groupId>com.tencentcloudapi</groupId>--> <!-- <groupId>com.tencentcloudapi</groupId>-->

View File

@ -44,6 +44,10 @@ public class BaseInfoProperties {
// 举报视频 // 举报视频
public static final String REDIS_VIDEO_BLOCK = "redis_video_block"; 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} // 用户是否喜欢/点赞视频取代数据库的关联关系1喜欢0不喜欢默认 redis_user_like_vlog:{userId}:{vlogId}
public static final String REDIS_USER_LIKE_VLOG = "redis_user_like_vlog"; public static final String REDIS_USER_LIKE_VLOG = "redis_user_like_vlog";

View File

@ -206,6 +206,7 @@ public class CommentServiceImpl extends BaseInfoProperties implements CommentSer
wrapper.eq(Comment::getVlogId, bo.getVlogId()); wrapper.eq(Comment::getVlogId, bo.getVlogId());
} }
wrapper.orderByDesc(Comment::getCreateTime);
Page<Comment> commentPage = commentMapper.selectPage(page, wrapper); Page<Comment> commentPage = commentMapper.selectPage(page, wrapper);
// 转VO并加子评论数 // 转VO并加子评论数

View File

@ -19,6 +19,7 @@ import com.wzj.soopin.content.enums.YesOrNo;
import com.wzj.soopin.content.mapper.CommentMapper; import com.wzj.soopin.content.mapper.CommentMapper;
import com.wzj.soopin.content.mapper.MyLikedVlogMapper; import com.wzj.soopin.content.mapper.MyLikedVlogMapper;
import com.wzj.soopin.content.mapper.UsersMapper; 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.member.mapper.MemberMapper;
import com.wzj.soopin.content.mapper.VlogMapper; import com.wzj.soopin.content.mapper.VlogMapper;
import com.wzj.soopin.content.mapper.VlogMapperCustom; 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.content.utils.TencentCloudUtil;
import com.wzj.soopin.member.service.IFansService; import com.wzj.soopin.member.service.IFansService;
import com.wzj.soopin.content.convert.VlogConvert; import com.wzj.soopin.content.convert.VlogConvert;
import com.wzj.soopin.member.service.IMemberService;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.exception.ServiceException; 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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; 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 org.dromara.common.core.utils.MapstructUtils;
import java.time.Instant; import java.time.Instant;
@ -80,10 +78,7 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
@Autowired @Autowired
private MemberMapper memberMapper; private MemberMapper memberMapper;
@Autowired @Autowired
private ISysMessageService sysMessageService; private IMemberService memberService;
@Autowired
private ISysMessageTemplateService templateService;
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Override @Override
public void updateVlogStatus(String fileId, Integer status, String reason) { public void updateVlogStatus(String fileId, Integer status, String reason) {
@ -100,23 +95,23 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
// 2. 选择模板假设你有模板ID实际可配置到常量或数据库 // 2. 选择模板假设你有模板ID实际可配置到常量或数据库
Long templateId = (status == 1) ? 1938491493736902658L : 1938491899007332353L; // 1001=审核通过模板1002=驳回模板 Long templateId = (status == 1) ? 1938491493736902658L : 1938491899007332353L; // 1001=审核通过模板1002=驳回模板
SysMessageTemplateVo template = templateService.selectTemplateById(templateId); // SysMessageTemplateVo template = templateService.selectTemplateById(templateId);
if (template == null) return; // if (template == null) return;
//
// 3. 参数替换 // // 3. 参数替换
String content = template.getTemplateContent() // String content = template.getTemplateContent()
.replace("${videoTitle}", vlog.getTitle() == null ? "" : vlog.getTitle()) // .replace("${videoTitle}", vlog.getTitle() == null ? "" : vlog.getTitle())
.replace("${reason}", reason == null ? "" : reason); // .replace("${reason}", reason == null ? "" : reason);
//
// 4. 构造消息对象 // // 4. 构造消息对象
SysMessageBo messageBo = new SysMessageBo(); // SysMessageBo messageBo = new SysMessageBo();
messageBo.setTitle(template.getTitle()); // messageBo.setTitle(template.getTitle());
messageBo.setContent(content); // messageBo.setContent(content);
messageBo.setSenderId(1L); // 系统管理员 // messageBo.setSenderId(1L); // 系统管理员
// 可根据需要设置更多字段 // // 可根据需要设置更多字段
//
// 5. 发送消息 // // 5. 发送消息
sysMessageService.sendMessageToUser(messageBo, Long.valueOf(uploaderId)); // sysMessageService.sendMessageToUser(messageBo, Long.valueOf(uploaderId));
} }
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@ -162,7 +157,7 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
if (StringUtils.isNotBlank(status)) { if (StringUtils.isNotBlank(status)) {
queryWrapper.eq(Vlog::getStatus, status); queryWrapper.eq(Vlog::getStatus, status);
} }
// Handle blocked videos // 去掉黑名单的视频
if (StringUtils.isNotBlank(userId)) { if (StringUtils.isNotBlank(userId)) {
String redisKey = REDIS_VIDEO_BLOCK + ":" + userId; String redisKey = REDIS_VIDEO_BLOCK + ":" + userId;
if (redis.keyIsExist(redisKey)) { if (redis.keyIsExist(redisKey)) {
@ -183,7 +178,7 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
} }
} }
} }
// Handle blocked users // 去掉黑名单的用户
if (StringUtils.isNotBlank(userId)) { if (StringUtils.isNotBlank(userId)) {
String redisKey = REDIS_USER_BLOCK + ":" + userId; String redisKey = REDIS_USER_BLOCK + ":" + userId;
if (redis.keyIsExist(redisKey)) { if (redis.keyIsExist(redisKey)) {
@ -196,7 +191,7 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
String memberId = (String) reportMap.get("MemberId"); String memberId = (String) reportMap.get("MemberId");
blockUserList.add(memberId); blockUserList.add(memberId);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
e.printStackTrace(); log.error(e.getMessage());
} }
} }
if (!blockUserList.isEmpty()) { 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); Page<Vlog> vlogPage = vlogMapper.selectPage(pageParam, queryWrapper);
List<Vlog> vlogList = vlogPage.getRecords(); List<Vlog> vlogList = vlogPage.getRecords();
List<IndexVlogVO> voList = vlogList.stream().map(v -> { List<IndexVlogVO> voList = vlogList.stream().map(v -> {
@ -214,28 +230,15 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
} }
vo.setLikeCounts(getVlogBeLikedCounts(v.getId())); vo.setLikeCounts(getVlogBeLikedCounts(v.getId()));
vo.setCommentsCounts(getVlogComment(v.getId())); vo.setCommentsCounts(getVlogComment(v.getId()));
return vo; MemberVO m =memberService.getMemberInfo(vo.getMemberId());
}).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) { if (m != null) {
vo.setAvatar(m.getAvatar()); vo.setAvatar(m.getAvatar());
vo.setNickname(m.getNickname()); vo.setNickname(m.getNickname());
} }
}); return vo;
} }).collect(Collectors.toList());
}
// 封装分页结果 // 封装分页结果
Page<IndexVlogVO> gridResult = new Page<IndexVlogVO>(); Page<IndexVlogVO> gridResult = new Page<IndexVlogVO>();
@ -397,23 +400,23 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
if (vlog != null) { if (vlog != null) {
String vlogerId = vlog.getMemberId(); String vlogerId = vlog.getMemberId();
if (!userId.equals(vlogerId)) { if (!userId.equals(vlogerId)) {
Long templateId = 1938491299175723009L; // Long templateId = 1938491299175723009L;
SysMessageTemplateVo template = templateService.selectTemplateById(templateId); // SysMessageTemplateVo template = templateService.selectTemplateById(templateId);
if (template != null) { // if (template != null) {
// 查询点赞用户昵称 // // 查询点赞用户昵称
Member liker = memberMapper.selectById(userId); // Member liker = memberMapper.selectById(userId);
String likerNickname = liker != null && liker.getNickname() != null ? liker.getNickname() : ""; // String likerNickname = liker != null && liker.getNickname() != null ? liker.getNickname() : "";
//
String content = template.getTemplateContent() // String content = template.getTemplateContent()
.replace("${videoTitle}", vlog.getTitle() == null ? "" : vlog.getTitle()) // .replace("${videoTitle}", vlog.getTitle() == null ? "" : vlog.getTitle())
.replace("${liker}", userId) // .replace("${liker}", userId)
.replace("${likerNickname}", likerNickname); // .replace("${likerNickname}", likerNickname);
SysMessageBo messageBo = new SysMessageBo(); // SysMessageBo messageBo = new SysMessageBo();
messageBo.setTitle(template.getTitle()); // messageBo.setTitle(template.getTitle());
messageBo.setContent(content); // messageBo.setContent(content);
messageBo.setSenderId(Long.valueOf(userId)); // messageBo.setSenderId(Long.valueOf(userId));
sysMessageService.sendMessageToUser(messageBo, Long.valueOf(vlogerId)); // sysMessageService.sendMessageToUser(messageBo, Long.valueOf(vlogerId));
} // }
} }
} }
} }

View File

@ -1,5 +1,6 @@
package com.wzj.soopin.content.task; package com.wzj.soopin.content.task;
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
import com.wzj.soopin.content.service.VlogService; import com.wzj.soopin.content.service.VlogService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -13,6 +14,7 @@ import org.springframework.stereotype.Component;
*/ */
@Slf4j @Slf4j
@Component @Component
@JobExecutor(name = "vlogHotDataTask" )
public class VlogScheduledTask { public class VlogScheduledTask {
@Autowired @Autowired
@ -22,8 +24,7 @@ public class VlogScheduledTask {
* 每天12点定时查询点赞最多的100条视频并存储到Redis * 每天12点定时查询点赞最多的100条视频并存储到Redis
* cron表达式0 0 12 * * ? (每天12点执行) * cron表达式0 0 12 * * ? (每天12点执行)
*/ */
@Scheduled(cron = "0 0 12 * * ?") public void jobExecute() {
public void cacheTopLikedVlogs() {
log.info("开始执行定时任务查询点赞最多的100条视频并存储到Redis"); log.info("开始执行定时任务查询点赞最多的100条视频并存储到Redis");
try { try {
vlogService.cacheTopLikedVlogs(100); vlogService.cacheTopLikedVlogs(100);

View File

@ -19,7 +19,18 @@
<groupId>org.dromara</groupId> <groupId>org.dromara</groupId>
<artifactId>ruoyi-common-core</artifactId> <artifactId>ruoyi-common-core</artifactId>
</dependency> </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> <dependency>
<groupId>org.dromara</groupId> <groupId>org.dromara</groupId>
<artifactId>ruoyi-common-doc</artifactId> <artifactId>ruoyi-common-doc</artifactId>
@ -34,6 +45,10 @@
<groupId>org.dromara</groupId> <groupId>org.dromara</groupId>
<artifactId>ruoyi-common-translation</artifactId> <artifactId>ruoyi-common-translation</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-rabbitmq</artifactId>
</dependency>
<!-- OSS功能模块 --> <!-- OSS功能模块 -->
<dependency> <dependency>

View File

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

View File

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

View File

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

View File

@ -1,37 +1,24 @@
package org.dromara.system.controller; package org.dromara.system.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 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 io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.MapstructUtils; 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.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log; import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType; import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.satoken.utils.LoginHelper; 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.SysMessage;
import org.dromara.system.domain.bo.SysMessageBo; 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.SysMessageVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISysMessageService; 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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; 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 { public class SysMessageController extends BaseController {
private final ISysMessageService messageService; private final ISysMessageService messageService;
private final ISysUserService userService;
private final ISysMessageTemplateService templateService;
// private final MemberMapper umsMemberMapper;
/** /**
* 获取当前用户ID * 获取当前用户ID
@ -80,6 +64,7 @@ public class SysMessageController extends BaseController {
return R.ok(messageService.selectMessageById(id)); return R.ok(messageService.selectMessageById(id));
} }
/** /**
* 发送消息 * 发送消息
*/ */
@ -88,261 +73,17 @@ public class SysMessageController extends BaseController {
@RepeatSubmit() @RepeatSubmit()
@PostMapping("/send") @PostMapping("/send")
public R<Void> send(@RequestBody SysMessageBo bo) { public R<Void> send(@RequestBody SysMessageBo bo) {
// 设置发送者ID为当前登录用户ID
bo.setSenderId(getUserId());
// 如果提供了模板ID则从模板中获取标题和内容 // 如果提供了模板ID则从模板中获取标题和内容
Long templateId = bo.getTemplateId(); Long templateId = bo.getTemplateId();
if (templateId != null) { if(templateId == null){
SysMessageTemplateVo template = templateService.selectTemplateById(templateId); return R.fail("模板不能为空");
if (template != null) {
// 使用模板的标题和内容
bo.setTitle(template.getTitle());
bo.setContent(template.getTemplateContent());
} else {
return R.fail("未找到指定的消息模板");
} }
messageService.send(bo);
return R.ok();
} }
// 验证消息内容是否为空
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));
}
/**
* 标记消息为已读
*/
// @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));
// }
} }

View File

@ -17,6 +17,7 @@ import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log; import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType; import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.web.core.BaseController; import org.dromara.common.web.core.BaseController;
import org.dromara.system.converter.SysMessageTemplateConvert;
import org.dromara.system.domain.SysMessageTemplate; import org.dromara.system.domain.SysMessageTemplate;
import org.dromara.system.domain.bo.SysMessageTemplateBo; import org.dromara.system.domain.bo.SysMessageTemplateBo;
import org.dromara.system.domain.vo.SysMessageTemplateVo; import org.dromara.system.domain.vo.SysMessageTemplateVo;
@ -39,6 +40,8 @@ public class SysMessageTemplateController extends BaseController {
private final ISysMessageTemplateService templateService; private final ISysMessageTemplateService templateService;
private final SysMessageTemplateConvert convert;
/** /**
* 查询消息模板列表 * 查询消息模板列表
*/ */
@ -88,7 +91,7 @@ public class SysMessageTemplateController extends BaseController {
@RepeatSubmit() @RepeatSubmit()
@PostMapping() @PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody SysMessageTemplateBo bo) { 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() @RepeatSubmit()
@PutMapping() @PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysMessageTemplateBo bo) { public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysMessageTemplateBo bo) {
return toAjax(templateService.updateById(bo.toEntity())); return toAjax(templateService.updateById(convert.toPo(bo)));
} }
/** /**

View File

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

View File

@ -1,11 +1,10 @@
package org.dromara.system.converter; package org.dromara.system.converter;
import org.dromara.common.web.core.BaseConverter;
import org.dromara.system.domain.SysMessage; import org.dromara.system.domain.SysMessage;
import org.dromara.system.domain.bo.SysMessageBo;
import org.dromara.system.domain.vo.SysMessageVo; import org.dromara.system.domain.vo.SysMessageVo;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/** /**
* 消息对象转换器 * 消息对象转换器
@ -13,27 +12,6 @@ import java.util.List;
* @author ruoyi * @author ruoyi
*/ */
@Mapper(componentModel = "spring") @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);
} }

View File

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

View File

@ -43,7 +43,7 @@ public class SysMessage extends BaseAudit {
private String subType; private String subType;
/** 发送者ID */ /** 发送者ID */
private Long senderId; private String senderId;
/** 定时发送时间 */ /** 定时发送时间 */
private Date scheduledTime; private Date scheduledTime;
@ -51,6 +51,9 @@ public class SysMessage extends BaseAudit {
/** 状态0未发送 1已发送 */ /** 状态0未发送 1已发送 */
private String status; private String status;
/** 发送范围1:全部用户, 2:按用户类型, 3:指定用户) */
private Integer sendScope;
/** 扩展参数 */ /** 扩展参数 */
@TableField(exist = false) @TableField(exist = false)
private Map<String, Object> params = new HashMap<>(); private Map<String, Object> params = new HashMap<>();
@ -62,4 +65,10 @@ public class SysMessage extends BaseAudit {
/** 模板参数 */ /** 模板参数 */
@TableField(exist = false) @TableField(exist = false)
private Map<String, Object> templateParams; private Map<String, Object> templateParams;
/**
* 模板ID
*/
private Long templateId;
private String ext;
} }

View File

@ -29,37 +29,39 @@ public class SysMessageTemplate extends BaseAudit {
/** /**
* 模板类型0通知 1公告 * 模板类型0通知 1公告
*/ */
private String templateType; private String type;
private String title; 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停用 * 状态0正常 1停用
*/ */
private String status; private String status;
//
// /** /**
// * 备注 * 消息类型
// */ */
// private String remark; private Integer action;
/**
* 备注
*/
private String description;
} }

View File

@ -1,5 +1,6 @@
package org.dromara.system.domain.bo; package org.dromara.system.domain.bo;
import cn.hutool.core.map.MapWrapper;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
@ -7,6 +8,7 @@ import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.dromara.common.core.domain.BaseBO;
import org.dromara.common.core.domain.model.BaseAudit; import org.dromara.common.core.domain.model.BaseAudit;
import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup; import org.dromara.common.core.validate.EditGroup;
@ -18,8 +20,12 @@ import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import org.dromara.system.domain.SysMessageTemplate;
/** /**
* 消息业务对象 * 消息业务对象
@ -29,12 +35,15 @@ import com.baomidou.mybatisplus.annotation.TableField;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ExcelIgnoreUnannotated @ExcelIgnoreUnannotated
public class SysMessageBo extends BaseAudit { public class SysMessageBo extends BaseBO<SysMessage> {
/** 主键ID */ /** 主键ID */
@ExcelProperty(value = "消息ID") @ExcelProperty(value = "消息ID")
private Long id; private Long id;
/** 发送者ID */
private String senderId;
/** 消息标题 */ /** 消息标题 */
// @NotBlank(message = "消息标题不能为空", groups = { AddGroup.class, EditGroup.class }) // @NotBlank(message = "消息标题不能为空", groups = { AddGroup.class, EditGroup.class })
@Size(min = 0, max = 100, message = "消息标题长度不能超过100个字符") @Size(min = 0, max = 100, message = "消息标题长度不能超过100个字符")
@ -46,39 +55,21 @@ public class SysMessageBo extends BaseAudit {
@ExcelProperty(value = "消息内容") @ExcelProperty(value = "消息内容")
private String content; 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:指定用户) */ /** 发送范围all:全部用户, userType:按用户类型, userIds:指定用户) */
@NotEmpty(message = "发送范围不能为空", groups = { AddGroup.class }) @NotEmpty(message = "发送范围不能为空", groups = { AddGroup.class })
private List<String> sendScope; private Integer sendScope;
/** 接收用户ID列表 */ /** 接收用户ID列表 */
private List<Long> userIds; private List<Long> idList;
/** 是否发送给所有用户 */
private Boolean sendToAll;
/** 扩展数据JSON格式 */ /** 扩展数据JSON格式 */
private String extraData; private String extraData;
/** 消息类型标识 1=指定角色 2=指定用户 3=指定群 */
private Integer logmess;
/** 模板ID */ /** 模板ID */
private Long templateId; private Long templateId;
@ -89,6 +80,42 @@ public class SysMessageBo extends BaseAudit {
/** 备注 */ /** 备注 */
private String remark; 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") @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "UTC")
private LocalDateTime startTime; 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") @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "UTC")
private LocalDateTime sendTime; private LocalDateTime sendTime;
/** 模板类型编号如1=关注2=取消关注等) */ /**
@TableField(exist = false) * 消息参数
private String templateType; */
private Map<String, Object> params;
/** 模板参数 */
@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;
}
/** /**
* 转换为查询条件 * 转换为查询条件
*/ */
@Override
public LambdaQueryWrapper<SysMessage> toWrapper() { public LambdaQueryWrapper<SysMessage> toWrapper() {
LambdaQueryWrapper<SysMessage> lqw = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SysMessage> lqw = new LambdaQueryWrapper<>();
lqw.like(StringUtils.isNotBlank(this.getTitle()), SysMessage::getTitle, this.getTitle()) lqw.like(StringUtils.isNotBlank(this.getTitle()), SysMessage::getTitle, this.getTitle())
.like(StringUtils.isNotBlank(this.getContent()), SysMessage::getContent, this.getContent()) .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); .orderByDesc(SysMessage::getCreateTime);
return lqw; 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;
}
} }

View File

@ -5,6 +5,7 @@ import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.dromara.common.core.domain.BaseBO;
import org.dromara.common.core.domain.model.BaseAudit; import org.dromara.common.core.domain.model.BaseAudit;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.AddGroup;
@ -24,8 +25,7 @@ import jakarta.validation.constraints.Size;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@AutoMapper(target = SysMessageTemplate.class, reverseConvertGenerate = false) public class SysMessageTemplateBo extends BaseBO<SysMessageTemplate> {
public class SysMessageTemplateBo extends BaseAudit {
/** /**
* 模板ID * 模板ID
@ -38,27 +38,27 @@ public class SysMessageTemplateBo extends BaseAudit {
*/ */
@NotBlank(message = "模板名称不能为空", groups = {AddGroup.class, EditGroup.class}) @NotBlank(message = "模板名称不能为空", groups = {AddGroup.class, EditGroup.class})
@Size(max = 100, message = "模板名称长度不能超过{max}个字符") @Size(max = 100, message = "模板名称长度不能超过{max}个字符")
private String templateName; private String name;
/** /**
* 模板编码 * 模板编码
*/ */
// @NotBlank(message = "模板编码不能为空", groups = { AddGroup.class, EditGroup.class }) // @NotBlank(message = "模板编码不能为空", groups = { AddGroup.class, EditGroup.class })
// @Size(max = 50, message = "模板编码长度不能超过{max}个字符") // @Size(max = 50, message = "模板编码长度不能超过{max}个字符")
// private String templateCode; private String code;
/** /**
* 模板类型SMS=短信 MAIL=邮件 WECHAT=微信 SYSTEM=系统消息 * 模板类型SMS=短信 MAIL=邮件 WECHAT=微信 SYSTEM=系统消息
*/ */
@NotBlank(message = "模板类型不能为空", groups = {AddGroup.class, EditGroup.class}) @NotBlank(message = "模板类型不能为空", groups = {AddGroup.class, EditGroup.class})
@Size(max = 20, message = "模板类型长度不能超过{max}个字符") @Size(max = 20, message = "模板类型长度不能超过{max}个字符")
private String templateType; private String type;
/** /**
* 模板内容 * 模板内容
*/ */
@NotBlank(message = "模板内容不能为空", groups = {AddGroup.class, EditGroup.class}) @NotBlank(message = "模板内容不能为空", groups = {AddGroup.class, EditGroup.class})
private String templateContent; private String content;
/** /**
* 状态0正常 1停用 * 状态0正常 1停用
@ -68,37 +68,24 @@ public class SysMessageTemplateBo extends BaseAudit {
* 标题 * 标题
*/ */
private String title; private String title;
// /**
// * 备注
// */
// private String remark;
/**
* 将当前对象转换为查询条件 private String ext;
*/
private String action;
private String description;
@Override
public LambdaQueryWrapper<SysMessageTemplate> toWrapper() { public LambdaQueryWrapper<SysMessageTemplate> toWrapper() {
LambdaQueryWrapper<SysMessageTemplate> lqw = new LambdaQueryWrapper<>(); return super.toWrapper().eq(id != null, SysMessageTemplate::getId, id)
lqw.like(StringUtils.isNotBlank(templateName), SysMessageTemplate::getTemplateName, templateName) .eq(StringUtils.isNotBlank(type), SysMessageTemplate::getType, type)
// .like(StringUtils.isNotBlank(templateCode), SysMessageTemplate::getTemplateCode, templateCode) .eq(StringUtils.isNotBlank(type), SysMessageTemplate::getType, type)
.eq(StringUtils.isNotBlank(templateType), SysMessageTemplate::getTemplateType, templateType) .eq(StringUtils.isNotBlank(name), SysMessageTemplate::getName, name)
.eq(StringUtils.isNotBlank(content), SysMessageTemplate::getContent, content)
.eq(StringUtils.isNotBlank(status), SysMessageTemplate::getStatus, status) .eq(StringUtils.isNotBlank(status), SysMessageTemplate::getStatus, status)
.orderByDesc(SysMessageTemplate::getCreateTime); .eq(StringUtils.isNotBlank(title), SysMessageTemplate::getTitle, title);
return lqw;
}
/**
* 转换为实体对象
*/
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;
} }
} }

View File

@ -1,5 +1,6 @@
package org.dromara.system.domain.vo; package org.dromara.system.domain.vo;
import com.baomidou.mybatisplus.annotation.TableId;
import io.github.linpeilie.annotations.AutoMapper; import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -16,11 +17,7 @@ import java.util.Date;
* @author ruoyi * @author ruoyi
*/ */
@Data @Data
@AutoMapper(target = SysMessageTemplate.class)
public class SysMessageTemplateVo implements Serializable { public class SysMessageTemplateVo implements Serializable {
private static final long serialVersionUID = 1L;
/** /**
* 模板ID * 模板ID
*/ */
@ -29,17 +26,17 @@ public class SysMessageTemplateVo implements Serializable {
/** /**
* 模板类型1通知 2公告 3消息 * 模板类型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停用 * 状态0正常 1停用
@ -81,8 +74,21 @@ public class SysMessageTemplateVo implements Serializable {
*/ */
private Date updateTime; private Date updateTime;
// /** /**
// * 备注 * 扩展参数
// */ */
// private String remark; private String ext;
/**
* 消息类型
*/
private Integer action;
/**
* 备注
*/
private String description;
private String params;
} }

View File

@ -38,6 +38,9 @@ public class SysMessageVo implements Serializable {
/** 消息内容 */ /** 消息内容 */
@ExcelProperty(value = "消息内容") @ExcelProperty(value = "消息内容")
private String content; private String content;
/** 扩展参数 */
@ExcelProperty(value = "扩展参数")
private String ext;
/** 消息类型AUTO自动/MANUAL手动 */ /** 消息类型AUTO自动/MANUAL手动 */
@ExcelProperty(value = "消息类型") @ExcelProperty(value = "消息类型")
@ -49,7 +52,7 @@ public class SysMessageVo implements Serializable {
/** 发送者ID */ /** 发送者ID */
@ExcelProperty(value = "发送者ID") @ExcelProperty(value = "发送者ID")
private Long senderId; private String senderId;
/** 发送者名称 */ /** 发送者名称 */
@ExcelProperty(value = "发送者") @ExcelProperty(value = "发送者")
@ -59,9 +62,6 @@ public class SysMessageVo implements Serializable {
@ExcelProperty(value = "定时发送时间") @ExcelProperty(value = "定时发送时间")
private Date scheduledTime; private Date scheduledTime;
// /** 状态0正常 1停用 */
// @ExcelProperty(value = "状态")
// private String status;
/** 创建时间 */ /** 创建时间 */
@ExcelProperty(value = "创建时间") @ExcelProperty(value = "创建时间")
@ -76,6 +76,7 @@ public class SysMessageVo implements Serializable {
/** 更新者 */ /** 更新者 */
private String updateBy; private String updateBy;
/** 扩展参数 */ private SysMessageTemplateVo template;
private Map<String, Object> params = new HashMap<>();
private Map<String, Object> params;
} }

View File

@ -1,7 +1,10 @@
package org.dromara.system.event; package org.dromara.system.event;
import cn.hutool.json.JSONObject;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.json.utils.JsonUtils;
import org.dromara.system.consumer.MessageRocketMQConsumer; import org.dromara.system.consumer.MessageRocketMQConsumer;
import org.dromara.system.domain.event.MessageEvent; import org.dromara.system.domain.event.MessageEvent;
@ -58,7 +61,7 @@ public class MessageEventListener {
boolean tencentIMSendSuccess = false; boolean tencentIMSendSuccess = false;
try { try {
// 消息发送者可能是系统或管理员这里使用固定的管理员账号作为发送者 // 消息发送者可能是系统或管理员这里使用固定的管理员账号作为发送者
String fromUserId = "administrator"; String fromUserId = event.getMessage().getSenderId();
String toUserId = userId; // 接收者是事件中的用户ID String toUserId = userId; // 接收者是事件中的用户ID
String content = event.getMessage().getContent(); // 只取content字段 String content = event.getMessage().getContent(); // 只取content字段
@ -78,14 +81,15 @@ public class MessageEventListener {
// 扩展字段可以在APP端获取 // 扩展字段可以在APP端获取
String ext = null; String ext = null;
if (event.getMessage().getParams() != null && !event.getMessage().getParams().isEmpty()) { if (StringUtils.isNotBlank(event.getMessage().getExt())) {
ext = JsonUtils.toJsonString(event.getMessage().getParams()); 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; String pushType = null;
if (params != null && params.containsKey("pushType")) { if (params != null && params.get("pushType")!=null) {
pushType = String.valueOf(params.get("pushType")); pushType = String.valueOf(params.get("pushType"));
} }
@ -126,7 +130,7 @@ public class MessageEventListener {
} }
} else { } else {
// 默认为单用户推送 // 默认为单用户推送
TencentIMServiceImpl.TencentIMResult imResult = tencentIMService.sendMessageToTencentIM(fromUserId, toUserId, content); TencentIMServiceImpl.TencentIMResult imResult = tencentIMService.sendMessageToTencentIM(fromUserId, toUserId, content,ext);
tencentIMSendSuccess = imResult.isSuccess(); tencentIMSendSuccess = imResult.isSuccess();
if (tencentIMSendSuccess) { if (tencentIMSendSuccess) {
log.info("腾讯IM推送成功userId={}, response={}", toUserId, imResult.getRawResponse()); log.info("腾讯IM推送成功userId={}, response={}", toUserId, imResult.getRawResponse());

View File

@ -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.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.system.domain.SysMessage; 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.SysMessageBo;
import org.dromara.system.domain.vo.SysMessageVo; import org.dromara.system.domain.vo.SysMessageVo;
@ -58,16 +59,17 @@ public interface ISysMessageService extends IService<SysMessage> {
* @param userIds 用户ID列表 (String类型) * @param userIds 用户ID列表 (String类型)
* @return 结果 * @return 结果
*/ */
int sendMessageToUsers(SysMessageBo message, List<String> userIds); int sendMessageToUsers(SysMessage message, SysMessageTemplate template,List<String> userIds);
/** // /**
* 发送自动消息 // *
* // * 发送自动消息
* @param message 消息信息 // *
* @param userIds 用户ID列表 // * @param message 消息信息
* @return 结果 // * @param userIds 用户ID列表
*/ // * @return 结果
int sendAutoMessage(SysMessageBo message, List<Long> userIds); // */
// int sendAutoMessage(SysMessageBo message, List<Long> userIds);
/** /**
* 标记消息为已读 * 标记消息为已读
@ -173,4 +175,11 @@ public interface ISysMessageService extends IService<SysMessage> {
*/ */
SysMessage selectEntityById(Long id); SysMessage selectEntityById(Long id);
/**
* 发送消息
* @param bo
* @return
*/
boolean send(SysMessageBo bo);
} }

View File

@ -41,21 +41,6 @@ public interface ISysMessageTemplateService extends IService<SysMessageTemplate>
*/ */
SysMessageTemplateVo selectTemplateById(Long id); SysMessageTemplateVo selectTemplateById(Long id);
/**
* 新增消息模板
*
* @param template 消息模板信息
* @return 结果
*/
int insertTemplate(SysMessageTemplateBo template);
/**
* 修改消息模板
*
* @param template 消息模板信息
* @return 结果
*/
int updateTemplate(SysMessageTemplateBo template);
/** /**
* 批量删除消息模板 * 批量删除消息模板
@ -80,4 +65,5 @@ public interface ISysMessageTemplateService extends IService<SysMessageTemplate>
* @return 消息模板列表 * @return 消息模板列表
*/ */
List<SysMessageTemplateVo> selectTemplateListByName(String name); List<SysMessageTemplateVo> selectTemplateListByName(String name);
SysMessageTemplate selectByTemplateType(String templateType) ;
} }

View File

@ -0,0 +1,6 @@
package org.dromara.system.service;
import org.dromara.system.domain.bo.SysMessageBo;
public interface ISystemMessageUserService {
}

View File

@ -19,8 +19,7 @@ public interface ITencentIMService {
* @param content 消息内容 * @param content 消息内容
* @return 是否发送成功 * @return 是否发送成功
*/ */
TencentIMServiceImpl.TencentIMResult sendMessageToTencentIM(String fromUserId, String toUserId, String content); TencentIMServiceImpl.TencentIMResult sendMessageToTencentIM(String fromUserId, String toUserId, String content, String cloudCustomData);
/** /**
* 推送消息给全体用户 * 推送消息给全体用户

View File

@ -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.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 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.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.text.StringSubstitutor; 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.MapstructUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; 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.SysMessage;
import org.dromara.system.domain.SysMessageTemplate; import org.dromara.system.domain.SysMessageTemplate;
import org.dromara.system.domain.SysMessageUser; import org.dromara.system.domain.SysMessageUser;
import org.dromara.system.domain.bo.SysMessageBo; import org.dromara.system.domain.bo.SysMessageBo;
import org.dromara.system.domain.event.MessageEvent; import org.dromara.system.domain.event.MessageEvent;
import org.dromara.system.domain.vo.SysMessageVo; 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.SysMessageMapper;
import org.dromara.system.mapper.SysMessageUserMapper; import org.dromara.system.mapper.SysMessageUserMapper;
import org.dromara.system.service.ISysMessageService; 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.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -41,8 +53,13 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
private final SysMessageMapper messageMapper; private final SysMessageMapper messageMapper;
private final SysMessageUserMapper messageUserMapper; private final SysMessageUserMapper messageUserMapper;
private final ApplicationEventPublisher eventPublisher; 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 @Override
public TableDataInfo<SysMessageVo> selectPageMessageList(SysMessageBo bo, PageQuery pageQuery) { public TableDataInfo<SysMessageVo> selectPageMessageList(SysMessageBo bo, PageQuery pageQuery) {
@ -89,19 +106,19 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
public int sendMessageToUser(SysMessageBo message, Long userId) { public int sendMessageToUser(SysMessageBo message, Long userId) {
// 新增通过模板类型编号查找并渲染模板轻量变量替换 // 新增通过模板类型编号查找并渲染模板轻量变量替换
if (StringUtils.isNotBlank(message.getTemplateType())) { if (StringUtils.isNotBlank(message.getTemplateType())) {
SysMessageTemplate template = messageTemplateService.selectByTemplateType(message.getTemplateType()); SysMessageTemplate template = templateService.selectByTemplateType(message.getTemplateType());
if (template == null) { if (template == null) {
throw new RuntimeException("消息模板不存在templateType=" + message.getTemplateType()); throw new RuntimeException("消息模板不存在templateType=" + message.getTemplateType());
} }
Map<String, Object> params = message.getTemplateParams(); 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); message.setContent(content);
} }
//加一个约定 //加一个约定
// 保存消息 // 保存消息
SysMessage entity = message.toEntity(); SysMessage entity = messageConvert.toPo(message);
Date scheduledTime = entity.getScheduledTime(); Date scheduledTime = entity.getScheduledTime();
entity.setStatus("1"); // 已发送 entity.setStatus("1"); // 已发送
messageMapper.insert(entity); messageMapper.insert(entity);
@ -132,13 +149,12 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
@Override @Override
@Transactional(rollbackFor = Exception.class) @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()) { if (userIds == null || userIds.isEmpty()) {
return 0; return 0;
} }
// 保存消息 // 保存消息
SysMessage entity = message.toEntity(); Date scheduledTime = message.getScheduledTime();
Date scheduledTime = entity.getScheduledTime();
// if (scheduledTime != null && scheduledTime.after(new Date())) { // if (scheduledTime != null && scheduledTime.after(new Date())) {
// entity.setStatus("0"); // 未发送 // entity.setStatus("0"); // 未发送
// messageMapper.insert(entity); // messageMapper.insert(entity);
@ -191,8 +207,7 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
// // 定时消息不发布事件 // // 定时消息不发布事件
// return count; // return count;
// } else { // } else {
entity.setStatus("1"); // 已发送
messageMapper.insert(entity);
// 批量创建消息用户关联 // 批量创建消息用户关联
int count = 0; int count = 0;
List<Long> validUserIds = new ArrayList<>(); List<Long> validUserIds = new ArrayList<>();
@ -211,7 +226,7 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
} }
if (!validUserIds.isEmpty()) { if (!validUserIds.isEmpty()) {
LambdaQueryWrapper<SysMessageUser> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SysMessageUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysMessageUser::getMessageId, entity.getId()) queryWrapper.eq(SysMessageUser::getMessageId, message.getId())
.in(SysMessageUser::getUserId, validUserIds); .in(SysMessageUser::getUserId, validUserIds);
List<SysMessageUser> existingRecords = messageUserMapper.selectList(queryWrapper); List<SysMessageUser> existingRecords = messageUserMapper.selectList(queryWrapper);
Set<Long> existingUserIds = existingRecords.stream() Set<Long> existingUserIds = existingRecords.stream()
@ -222,7 +237,7 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
if (!existingUserIds.contains(userId)) { if (!existingUserIds.contains(userId)) {
try { try {
SysMessageUser messageUser = new SysMessageUser(); SysMessageUser messageUser = new SysMessageUser();
messageUser.setMessageId(entity.getId()); messageUser.setMessageId(message.getId());
messageUser.setUserId(userId); messageUser.setUserId(userId);
messageUser.setIsRead(false); messageUser.setIsRead(false);
int rows = messageUserMapper.insert(messageUser); int rows = messageUserMapper.insert(messageUser);
@ -231,18 +246,25 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
} }
} catch (Exception e) { } catch (Exception e) {
log.error("创建消息用户关联失败: messageId={}, userId={}, error={}", log.error("创建消息用户关联失败: messageId={}, userId={}, error={}",
entity.getId(), userId, e.getMessage()); message.getId(), userId, e.getMessage());
} }
} else { } else {
log.info("消息与用户关联已存在,跳过创建: messageId={}, userId={}", entity.getId(), userId); log.info("消息与用户关联已存在,跳过创建: messageId={}, userId={}", message.getId(), userId);
count++; count++;
} }
} }
} }
// 最后只发送一次批量事件通知 // 最后只发送一次批量事件通知
if (count > 0) { 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) { 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)); eventPublisher.publishEvent(new MessageEvent(this, messageVo, userId));
} }
} }
@ -250,12 +272,12 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
// } // }
} }
@Override // @Override
@Transactional(rollbackFor = Exception.class) // @Transactional(rollbackFor = Exception.class)
public int sendAutoMessage(SysMessageBo message, List<Long> userIds) { // public int sendAutoMessage(SysMessageBo message, List<Long> userIds) {
message.setMsgType("AUTO"); // message.setMsgType("AUTO");
return sendMessageToUsers(message, userIds.stream().map(String::valueOf).collect(Collectors.toList())); // return sendMessageToUsers(message, userIds.stream().map(String::valueOf).collect(Collectors.toList()));
} // }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@ -295,8 +317,6 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
LambdaQueryWrapper<SysMessage> lqw = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SysMessage> lqw = new LambdaQueryWrapper<>();
lqw.eq(StringUtils.isNotBlank(message.getMsgType()), SysMessage::getMsgType, message.getMsgType()) lqw.eq(StringUtils.isNotBlank(message.getMsgType()), SysMessage::getMsgType, message.getMsgType())
.eq(StringUtils.isNotBlank(message.getSubType()), SysMessage::getSubType, message.getSubType()) .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); .orderByDesc(SysMessage::getCreateTime);
return MapstructUtils.convert(messageMapper.selectList(lqw), SysMessageVo.class); return MapstructUtils.convert(messageMapper.selectList(lqw), SysMessageVo.class);
} }
@ -308,12 +328,12 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
@Override @Override
public int insertMessage(SysMessageBo message) { public int insertMessage(SysMessageBo message) {
return messageMapper.insert(message.toEntity()); return messageMapper.insert(messageConvert.toPo(message));
} }
@Override @Override
public int updateMessage(SysMessageBo message) { public int updateMessage(SysMessageBo message) {
return messageMapper.updateById(message.toEntity()); return messageMapper.updateById(messageConvert.toPo(message));
} }
@Override @Override
@ -350,7 +370,7 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
// 尝试以字符串形式发送 // 尝试以字符串形式发送
// 保存消息 // 保存消息
SysMessage entity = message.toEntity(); SysMessage entity = messageConvert.toPo(message);
messageMapper.insert(entity); messageMapper.insert(entity);
// 发送事件通知 // 发送事件通知
@ -382,4 +402,121 @@ public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMess
return messageMapper.selectById(id); 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;
}
} }

View File

@ -31,12 +31,6 @@ public class SysMessageTemplateServiceImpl extends ServiceImpl<SysMessageTemplat
@Override @Override
public TableDataInfo<SysMessageTemplateVo> selectTemplatePage(SysMessageTemplateBo bo, PageQuery pageQuery) { public TableDataInfo<SysMessageTemplateVo> selectTemplatePage(SysMessageTemplateBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<SysMessageTemplate> lqw = new LambdaQueryWrapper<>(); 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> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
Page<SysMessageTemplate> resultPage = templateMapper.selectPage(page, lqw); Page<SysMessageTemplate> resultPage = templateMapper.selectPage(page, lqw);
List<SysMessageTemplateVo> records = MapstructUtils.convert(resultPage.getRecords(), SysMessageTemplateVo.class); List<SysMessageTemplateVo> records = MapstructUtils.convert(resultPage.getRecords(), SysMessageTemplateVo.class);
@ -47,13 +41,7 @@ public class SysMessageTemplateServiceImpl extends ServiceImpl<SysMessageTemplat
@Override @Override
public List<SysMessageTemplateVo> selectTemplateList(SysMessageTemplateBo bo) { public List<SysMessageTemplateVo> selectTemplateList(SysMessageTemplateBo bo) {
LambdaQueryWrapper<SysMessageTemplate> lqw = new LambdaQueryWrapper<>(); return MapstructUtils.convert(templateMapper.selectList(bo.toWrapper()), SysMessageTemplateVo.class);
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);
} }
@Override @Override
@ -61,16 +49,6 @@ public class SysMessageTemplateServiceImpl extends ServiceImpl<SysMessageTemplat
return MapstructUtils.convert(templateMapper.selectById(id), SysMessageTemplateVo.class); 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 @Override
public int deleteTemplateByIds(Long[] ids) { public int deleteTemplateByIds(Long[] ids) {
return templateMapper.deleteBatchIds(List.of(ids)); return templateMapper.deleteBatchIds(List.of(ids));
@ -85,7 +63,7 @@ public class SysMessageTemplateServiceImpl extends ServiceImpl<SysMessageTemplat
public List<SysMessageTemplateVo> selectTemplateListByName(String name) { public List<SysMessageTemplateVo> selectTemplateListByName(String name) {
LambdaQueryWrapper<SysMessageTemplate> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SysMessageTemplate> queryWrapper = new LambdaQueryWrapper<>();
if (StringUtils.isNotBlank(name)) { if (StringUtils.isNotBlank(name)) {
queryWrapper.like(SysMessageTemplate::getTemplateName, name); queryWrapper.like(SysMessageTemplate::getName, name);
} }
queryWrapper.orderByDesc(SysMessageTemplate::getCreateTime); queryWrapper.orderByDesc(SysMessageTemplate::getCreateTime);
return MapstructUtils.convert(templateMapper.selectList(queryWrapper), SysMessageTemplateVo.class); return MapstructUtils.convert(templateMapper.selectList(queryWrapper), SysMessageTemplateVo.class);
@ -94,9 +72,10 @@ public class SysMessageTemplateServiceImpl extends ServiceImpl<SysMessageTemplat
/** /**
* 根据模板类型编号查找模板 * 根据模板类型编号查找模板
*/ */
@Override
public SysMessageTemplate selectByTemplateType(String templateType) { public SysMessageTemplate selectByTemplateType(String templateType) {
LambdaQueryWrapper<SysMessageTemplate> lqw = new LambdaQueryWrapper<>(); 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); return templateMapper.selectOne(lqw);
} }
} }

View File

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

View File

@ -1,5 +1,6 @@
package org.dromara.system.service.impl; package org.dromara.system.service.impl;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -170,7 +171,7 @@ public class TencentIMServiceImpl implements ITencentIMService {
} }
@Override @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(); TencentIMResult result = new TencentIMResult();
try { try {
String userSig = generateAdminUserSig(); String userSig = generateAdminUserSig();
@ -182,17 +183,16 @@ public class TencentIMServiceImpl implements ITencentIMService {
adminAccount, adminAccount,
userSig, userSig,
random); random);
Map<String, Object> msgContent = new HashMap<>();
msgContent.put("Text", content); JSONArray jsonArray=new JSONArray();
Map<String, Object> msgBody = new HashMap<>(); jsonArray.add(new JSONObject(msgBody));
msgBody.put("MsgType", "TIMTextElem"); JSONObject requestBody = new JSONObject();
msgBody.put("MsgContent", msgContent);
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("SyncOtherMachine", 2); requestBody.put("SyncOtherMachine", 2);
requestBody.put("From_Account", fromUserId); requestBody.put("From_Account", fromUserId);
requestBody.put("To_Account", toUserId); requestBody.put("To_Account", toUserId);
requestBody.put("MsgRandom", Integer.parseInt(random)); requestBody.put("MsgRandom", Integer.parseInt(random));
requestBody.put("MsgBody", new Object[]{msgBody}); requestBody.put("MsgBody", jsonArray);
requestBody.put("CloudCustomData", cloudCustomData);
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON); headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers); 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("MsgRandom", Integer.parseInt(random));
requestBody.put("MsgBody", new Object[]{msgBody}); requestBody.put("MsgBody", new Object[]{msgBody});
requestBody.put("CloudCustomData", ext);
// 设置离线推送信息 // 设置离线推送信息
if (offlinePush) { if (offlinePush) {
Map<String, Object> offlinePushInfo = new HashMap<>(); Map<String, Object> offlinePushInfo = new HashMap<>();

View File

@ -34,10 +34,7 @@
<groupId>org.dromara</groupId> <groupId>org.dromara</groupId>
<artifactId>ruoyi-common-translation</artifactId> <artifactId>ruoyi-common-translation</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-im</artifactId>
</dependency>
<!-- OSS功能模块 --> <!-- OSS功能模块 -->
<dependency> <dependency>
<groupId>org.dromara</groupId> <groupId>org.dromara</groupId>

View File

@ -124,7 +124,7 @@ public class FansController {
log.warn("IM回调Pair参数转换失败: {}", pair); log.warn("IM回调Pair参数转换失败: {}", pair);
continue; continue;
} }
handleImFollow(fromId, java.util.Arrays.asList(toId)); service.doFollow(fromId, toId);
log.info("IM回调处理成功: fromId={}, vloggerId={}", fromId, toId); log.info("IM回调处理成功: fromId={}, vloggerId={}", fromId, toId);
} else { } else {
log.warn("IM回调Pair参数不完整: {}", pair); log.warn("IM回调Pair参数不完整: {}", pair);

View File

@ -25,7 +25,6 @@ public class ImCallbackController {
private static final Logger log = LoggerFactory.getLogger(ImCallbackController.class); private static final Logger log = LoggerFactory.getLogger(ImCallbackController.class);
// private static final String CALLBACK_TOKEN = "your_auth_token"; // // private static final String CALLBACK_TOKEN = "your_auth_token"; //
@Autowired @Autowired
private IMemberService memberService; private IMemberService memberService;
@Autowired @Autowired
@ -55,11 +54,11 @@ public class ImCallbackController {
return R.fail(1002, "缺少CallbackCommand"); return R.fail(1002, "缺少CallbackCommand");
} }
switch (callbackCommand) { switch (callbackCommand) {
case "Sns.CallbackFriendAdd": case "Sns.CallbackFriendAdd"://好友添加
// 关注直接调用 FansController follow // 关注直接调用 FansController follow
fansController.follow(requestBody, null, null); fansController.follow(requestBody, null, null);
break; break;
case "Sns.CallbackFriendDelete": case "Sns.CallbackFriendDelete"://好友删除
// 取关直接调用 FansController cancel // 取关直接调用 FansController cancel
fansController.cancel(requestBody, null, null); fansController.cancel(requestBody, null, null);
break; break;
@ -73,6 +72,12 @@ public class ImCallbackController {
case "Sns.CallbackBlackListDelete": case "Sns.CallbackBlackListDelete":
handleImCancelBlock(requestBody); handleImCancelBlock(requestBody);
break; break;
case "Follow.CallbackAfterFollowAdd"://关注
fansController.follow(requestBody, null, null);
break;
case "Follow.CallbackAfterFollowDelete"://取关
fansController.cancel(requestBody, null, null);
break;
default: default:
log.info("收到未知事件类型: {}, 参数: {}", callbackCommand, requestBody); log.info("收到未知事件类型: {}, 参数: {}", callbackCommand, requestBody);
break; break;

View File

@ -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.bo.MemberAddressBO;
import com.wzj.soopin.member.domain.po.MemberAddress; import com.wzj.soopin.member.domain.po.MemberAddress;
import com.wzj.soopin.member.domain.vo.MemberAddressVO; import com.wzj.soopin.member.domain.vo.MemberAddressVO;
import org.dromara.system.mapper.AddressMapper;
import com.wzj.soopin.member.service.IMemberAddressService; import com.wzj.soopin.member.service.IMemberAddressService;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; 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.excel.utils.ExcelUtil;
import org.dromara.common.log.annotation.Log; import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType; import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.redis.redis.RedisService;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.*; import java.util.List;
/** /**
* 会员收货地址Controller * 会员收货地址Controller

View File

@ -64,7 +64,7 @@ public class MemberController extends BaseController {
@Tag(name ="获取会员信息详细信息") @Tag(name ="获取会员信息详细信息")
@GetMapping(value = "{id}") @GetMapping(value = "{id}")
public R<MemberVO> getInfo(@PathVariable("id") Long 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 ="新增会员信息") @Tag(name ="新增会员信息")

View File

@ -5,25 +5,20 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wzj.soopin.member.domain.po.Fans; 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.domain.vo.FansVO;
import com.wzj.soopin.member.mapper.FansMapper; import com.wzj.soopin.member.mapper.FansMapper;
import com.wzj.soopin.member.service.IFansService; import com.wzj.soopin.member.service.IFansService;
import com.wzj.soopin.member.service.IMemberService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.CacheConstants; import org.dromara.common.core.constant.CacheConstants;
import org.dromara.common.core.enums.YesOrNo; import org.dromara.common.core.enums.YesOrNo;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.redis.config.RedisConfig;
import org.dromara.common.redis.redis.RedisCache; import org.dromara.common.redis.redis.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; 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.HashMap;
import java.util.Map; import java.util.Map;
@ -35,10 +30,7 @@ public class FansServiceImpl extends ServiceImpl<FansMapper, Fans> implements IF
private final RedisCache redisCache; private final RedisCache redisCache;
@Autowired
private ISysMessageService sysMessageService;
@Autowired
private ISysMessageTemplateService templateService;
@Autowired @Autowired
private IMemberService memberService; private IMemberService memberService;
@ -72,17 +64,17 @@ public class FansServiceImpl extends ServiceImpl<FansMapper, Fans> implements IF
Member vlogger = memberService.getById(vloggerId); Member vlogger = memberService.getById(vloggerId);
if (follower != null && vlogger != null && !myId.equals(vloggerId)) { if (follower != null && vlogger != null && !myId.equals(vloggerId)) {
// 新版使用模板类型编号和参数 // 新版使用模板类型编号和参数
Map<String, Object> params = new HashMap<>(); // Map<String, Object> params = new HashMap<>();
params.put("followerNickname", follower.getNickname() == null ? "" : follower.getNickname()); // params.put("followerNickname", follower.getNickname() == null ? "" : follower.getNickname());
params.put("vloggerNickname", vlogger.getNickname() == null ? "" : vlogger.getNickname()); // params.put("vloggerNickname", vlogger.getNickname() == null ? "" : vlogger.getNickname());
SysMessageBo messageBo = new SysMessageBo(); // SysMessageBo messageBo = new SysMessageBo();
// 关注类型编号 // // 关注类型编号
messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.FOLLOW); // messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.FOLLOW);
messageBo.setTemplateParams(params); // messageBo.setTemplateParams(params);
messageBo.setSenderId(myId); // messageBo.setSenderId(myId);
// 补充设置消息标题防止title为null // // 补充设置消息标题防止title为null
messageBo.setTitle("关注通知"); // messageBo.setTitle("关注通知");
sysMessageService.sendMessageToUser(messageBo, vloggerId); // sysMessageService.sendMessageToUser(messageBo, vloggerId);
} }
} }
@ -122,16 +114,16 @@ public class FansServiceImpl extends ServiceImpl<FansMapper, Fans> implements IF
Member vlogger = memberService.getById(vloggerId); Member vlogger = memberService.getById(vloggerId);
if (follower != null && vlogger != null && !myId.equals(vloggerId)) { if (follower != null && vlogger != null && !myId.equals(vloggerId)) {
// 新版使用模板类型编号和参数 // 新版使用模板类型编号和参数
Map<String, Object> params = new HashMap<>(); // Map<String, Object> params = new HashMap<>();
params.put("followerNickname", follower.getNickname() == null ? "" : follower.getNickname()); // params.put("followerNickname", follower.getNickname() == null ? "" : follower.getNickname());
params.put("vloggerNickname", vlogger.getNickname() == null ? "" : vlogger.getNickname()); // params.put("vloggerNickname", vlogger.getNickname() == null ? "" : vlogger.getNickname());
SysMessageBo messageBo = new SysMessageBo(); // SysMessageBo messageBo = new SysMessageBo();
messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.UNFOLLOW); // 取关类型编号 // messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.UNFOLLOW); // 取关类型编号
messageBo.setTemplateParams(params); // messageBo.setTemplateParams(params);
messageBo.setSenderId(myId); // messageBo.setSenderId(myId);
// 补充设置消息标题防止title为null // // 补充设置消息标题防止title为null
messageBo.setTitle("取消关注通知"); // messageBo.setTitle("取消关注通知");
sysMessageService.sendMessageToUser(messageBo, vloggerId); // sysMessageService.sendMessageToUser(messageBo, vloggerId);
} }
} }

View File

@ -20,6 +20,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.CacheConstants; import org.dromara.common.core.constant.CacheConstants;
import org.dromara.common.core.constant.CachePrefix; 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.constant.ResultCode;
import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
@ -95,7 +96,7 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper,Member> implemen
return true; return true;
} }
@CacheEvict(value = CacheConstants.MEMBER, key = "#id") @CacheEvict(value = GlobalConstants.MEMBER_KEY, key = "#id")
public int updateMark(MemberBO member) { public int updateMark(MemberBO member) {
UpdateWrapper<Member> updateWrapper = new UpdateWrapper<>(); UpdateWrapper<Member> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("mark",member.getMark()) 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) { public Integer changeStatus(MemberBO bo) {
UpdateWrapper<Member> wrapper = new UpdateWrapper<>(); UpdateWrapper<Member> wrapper = new UpdateWrapper<>();
wrapper.eq("id", bo.getId()); wrapper.eq("id", bo.getId());
@ -258,7 +259,7 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper,Member> implemen
@Override @Override
@Cacheable (cacheNames = CacheConstants.MEMBER, key = "#id") @Cacheable (cacheNames = GlobalConstants.MEMBER_KEY , key = "#id")
public MemberVO getMemberInfo(Serializable id) { public MemberVO getMemberInfo(Serializable id) {
return memberConvert.toVO(getById(id)); return memberConvert.toVO(getById(id));
} }

View File

@ -162,10 +162,7 @@
<groupId>org.dromara</groupId> <groupId>org.dromara</groupId>
<artifactId>ruoyi-content</artifactId> <artifactId>ruoyi-content</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-im</artifactId>
</dependency>
<!-- 微信支付V3 SDK --> <!-- 微信支付V3 SDK -->
<dependency> <dependency>
<groupId>com.github.wechatpay-apiv3</groupId> <groupId>com.github.wechatpay-apiv3</groupId>

View File

@ -79,7 +79,7 @@ public class OrderController extends BaseController {
if (result != null) { if (result != null) {
// 订单创建成功发送消息 // 订单创建成功发送消息
service.sendMessage(order); // service.sendMessage(order);
log.info("订单创建成功消息已发送订单ID: {}", order.getId()); log.info("订单创建成功消息已发送订单ID: {}", order.getId());
} else { } else {
log.warn("订单创建失败: {}", "返回结果为null"); log.warn("订单创建失败: {}", "返回结果为null");

View File

@ -1,17 +1,18 @@
package com.wzj.soopin.order.service.impl; 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.CollUtil;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; 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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wzj.soopin.goods.domain.entity.Sku; import com.wzj.soopin.goods.domain.entity.Sku;
import com.wzj.soopin.goods.mapper.SkuMapper; import com.wzj.soopin.goods.mapper.SkuMapper;
import com.wzj.soopin.member.domain.po.Member; 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.bo.OrderBo;
import com.wzj.soopin.order.domain.entity.*; import com.wzj.soopin.order.domain.entity.*;
import com.wzj.soopin.order.domain.form.DeliverProductForm; 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.redis.redis.RedisService;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.SysTenant; 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.mapper.SysTenantMapper;
import org.dromara.system.service.ISysMessageTemplateService;
import org.dromara.system.service.impl.SysMessageServiceImpl;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
@ -63,8 +60,6 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
private final OrderDeliveryHistoryMapper orderDeliveryHistoryMapper; private final OrderDeliveryHistoryMapper orderDeliveryHistoryMapper;
private final VerificationCodeService verificationCodeService; private final VerificationCodeService verificationCodeService;
private final SysTenantMapper sysTenantMapper; private final SysTenantMapper sysTenantMapper;
private final ISysMessageTemplateService templateService;
private final SysMessageServiceImpl sysMessageService;
private final MemberWechatMapper memberWechatMapper; private final MemberWechatMapper memberWechatMapper;
private final WechatPaymentHistoryMapper wechatPaymentHistoryMapper; private final WechatPaymentHistoryMapper wechatPaymentHistoryMapper;
private final RedisService redisService; 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)); return baseMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderSn,orderNo));
} }
public void sendMessage(Order order) { // public void sendMessage(Order order) {
Long memberId = order.getMemberId(); // Long memberId = order.getMemberId();
Long orderId = order.getId(); // Long orderId = order.getId();
// 订单创建成功模板ID // // 订单创建成功模板ID
Long templateId =1940586928850100226L; // Long templateId =1940586928850100226L;
// 查询模板信息 // // 查询模板信息
SysMessageTemplateVo template = templateService.selectTemplateById(templateId); // SysMessageTemplateVo template = templateService.selectTemplateById(templateId);
log.info("模板信息为: {}", template); // log.info("模板信息为: {}", template);
//
if (template != null) { // if (template != null) {
Map<String, Object> params = new HashMap<>(); // Map<String, Object> params = new HashMap<>();
params.put("orderSn", order.getOrderSn()); // params.put("orderSn", order.getOrderSn());
params.put("productName", orderItemMapper.getName(orderId)); // params.put("productName", orderItemMapper.getName(orderId));
SysMessageBo messageBo = new SysMessageBo(); // SysMessageBo messageBo = new SysMessageBo();
messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.ORDER_NOTICE); // messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.ORDER_NOTICE);
messageBo.setTemplateParams(params); // messageBo.setTemplateParams(params);
messageBo.setSenderId(memberId); // messageBo.setSenderId(memberId);
messageBo.setTitle(template.getTitle()); // messageBo.setTitle(template.getTitle());
sysMessageService.sendMessageToUser(messageBo, memberId); // sysMessageService.sendMessageToUser(messageBo, memberId);
} // }
} // }
/** /**
* 处理退款逻辑 * 处理退款逻辑

View File

@ -15,10 +15,6 @@ import com.wzj.soopin.order.utils.StringUtils;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R; 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 org.springframework.stereotype.Service;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -40,8 +36,6 @@ public class VerificationCodeServiceImpl extends ServiceImpl<VerificationCodesM
private final OrderMapper orderMapper; private final OrderMapper orderMapper;
private final QrCodeGenerator qrCodeGenerator; private final QrCodeGenerator qrCodeGenerator;
private final VerificationLogsMapper logMapper; 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<>(); Map<String, Object> params = new HashMap<>();
// params.put("productName", productName); // params.put("productName", productName);
params.put("verificationTime", formattedTime); params.put("verificationTime", formattedTime);
SysMessageBo messageBo = new SysMessageBo(); // SysMessageBo messageBo = new SysMessageBo();
// 核销成功类型编号 // // 核销成功类型编号
messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.VERIFY_SUCCESS); // messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.VERIFY_SUCCESS);
messageBo.setTemplateParams(params); // messageBo.setTemplateParams(params);
messageBo.setSenderId(memberId); // messageBo.setSenderId(memberId);
// 补充设置消息标题 // // 补充设置消息标题
messageBo.setTitle("核销成功通知"); // messageBo.setTitle("核销成功通知");
sysMessageService.sendMessageToUser(messageBo, memberId); // sysMessageService.sendMessageToUser(messageBo, memberId);
} }
@Override @Override
@ -253,13 +247,13 @@ public class VerificationCodeServiceImpl extends ServiceImpl<VerificationCodesM
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
// params.put("productName", productName); // params.put("productName", productName);
params.put("reason", reason); params.put("reason", reason);
SysMessageBo messageBo = new SysMessageBo(); // SysMessageBo messageBo = new SysMessageBo();
// 核销失败类型编号 // // 核销失败类型编号
messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.VERIFY_FAIL); // messageBo.setTemplateType(org.dromara.system.domain.MessageTemplateType.VERIFY_FAIL);
messageBo.setTemplateParams(params); // messageBo.setTemplateParams(params);
messageBo.setSenderId(memberId); // messageBo.setSenderId(memberId);
// 补充设置消息标题 // // 补充设置消息标题
messageBo.setTitle("核销失败通知"); // messageBo.setTitle("核销失败通知");
sysMessageService.sendMessageToUser(messageBo, memberId); // sysMessageService.sendMessageToUser(messageBo, memberId);
} }
} }