解决编译报错

This commit is contained in:
easonzhu 2025-02-03 18:59:51 +08:00
parent cae0d65443
commit 494970db37
45 changed files with 2568 additions and 7 deletions

33
pom.xml
View File

@ -151,5 +151,38 @@
<artifactId>bcprov-jdk15on</artifactId> <artifactId>bcprov-jdk15on</artifactId>
<version>1.66</version> <version>1.66</version>
</dependency> </dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>4.5.1</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<skipTests>true</skipTests>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.upchina.startup.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -17,6 +17,9 @@ public class AdvisorBasic implements Serializable {
public String profile; public String profile;
public String phone; public String phone;
public AdvisorBasic() {
}
public AdvisorBasic(AdvisorInfo advisorInfo, String deptName) { public AdvisorBasic(AdvisorInfo advisorInfo, String deptName) {
this.id = advisorInfo.getId(); this.id = advisorInfo.getId();
this.userId = advisorInfo.getUserId(); this.userId = advisorInfo.getUserId();

View File

@ -403,9 +403,21 @@ public class CacheKey {
public static final String GROUP = "group"; public static final String GROUP = "group";
// 消息主题
public static class GroupMessageTopicKey {
public static final String ADMIN_GROUP_TOPIC = "admin_group_topic";
public static final String ADMIN_PRIVATE_TOPIC = "admin_private_topic";
public static final String ADMIN_SESSION_TOPIC = "admin_session_topic";
public static final String APP_GROUP_TOPIC = "app_group_topic";
public static final String APP_PRIVATE_TOPIC = "app_private_topic";
public static final String APP_SESSION_TOPIC = "app_session_topic";
}
public static class GroupKey { public static class GroupKey {
public static final String GROUP_INFO = "group|info|"; public static final String GROUP_INFO = "group|info|";
public static final String MAIN_GROUP_LIST = "group|main|list|"; public static final String MAIN_GROUP_LIST = "group|main|list|";
public static final String GROUP_MESSAGE_LIST = "group|message|list|";
public static final String GROUP_MESSAGE_DETAIL = "group|message|detail|";
} }
} }

View File

@ -7,7 +7,6 @@ import com.upchina.common.vo.FrontUserVO;
import com.upchina.video.entity.OnlineUser; import com.upchina.video.entity.OnlineUser;
import com.upchina.video.service.common.VideoCacheService; import com.upchina.video.service.common.VideoCacheService;
import com.upchina.video.service.common.VideoMessageService; import com.upchina.video.service.common.VideoMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor; import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;

View File

@ -127,6 +127,7 @@ public enum ResponseStatus {
DECRYPT_ERROR(4059, "AES解密失败"), DECRYPT_ERROR(4059, "AES解密失败"),
SECRET_ACQUIRE_FAIL(4060, "获取加密推送地址失败"), SECRET_ACQUIRE_FAIL(4060, "获取加密推送地址失败"),
MESSAGE_PERMISSION_ERROR(4061, "消息权限错误"),
/*********************内部系统***********************/ /*********************内部系统***********************/
SYS_BUSY(5000, "系统忙,请稍后重试"), SYS_BUSY(5000, "系统忙,请稍后重试"),

View File

@ -0,0 +1,23 @@
package com.upchina.common.state;
import com.upchina.group.constant.GroupMessageStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GroupMessageStateMachine {
@Bean
public StateMachine<GroupMessageStatus> groupMessageSM() {
StateMachine<GroupMessageStatus> groupMessageSM = new StateMachine<>();
// 初始 -> 审核 -> 已审核
groupMessageSM.add(GroupMessageStatus.INITIAL, GroupMessageStatus.AUDITED);
// 初始 -> 删除 -> 已删除
groupMessageSM.add(GroupMessageStatus.INITIAL, GroupMessageStatus.DELETED);
// 已审核 -> 删除 -> 已删除
groupMessageSM.add(GroupMessageStatus.AUDITED, GroupMessageStatus.DELETED);
return groupMessageSM;
}
}

View File

@ -0,0 +1,16 @@
package com.upchina.group.constant;
public enum GroupInteractiveType {
GROUP(1, "群聊"),
PRIVATE(2, "私聊"),
SESSION(3, "会话消息"),
;
public final Integer value;
public final String desc;
GroupInteractiveType(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
}

View File

@ -0,0 +1,17 @@
package com.upchina.group.constant;
// 消息类型1APP2ADMIN
public enum GroupMessageChannel {
APP(1, "APP"),
ADMIN(2, "ADMIN"),
ALL(3, "ALL");
;
public final Integer value;
public final String name;
GroupMessageChannel(Integer value, String name) {
this.value = value;
this.name = name;
}
}

View File

@ -0,0 +1,17 @@
package com.upchina.group.constant;
public enum GroupMessageContentType {
TEXT(1, "文本"),
IMAGE(2, "图片"),
FILE(3, "文件"),
PRODUCT(4, "产品"),
QUESTIONNAIRE(5, "问卷");
public final Integer value;
public final String desc;
GroupMessageContentType(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
}

View File

@ -0,0 +1,27 @@
package com.upchina.group.constant;
public enum GroupMessageStatus {
INITIAL(1, "初始"),
AUDITED(2, "已审核"),
DELETED(3, "已删除");
public final Integer value;
public final String desc;
GroupMessageStatus(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
public static GroupMessageStatus fromValue(Integer value) {
if (value == null) {
return null;
}
for (GroupMessageStatus status : values()) {
if (status.value.equals(value)) {
return status;
}
}
return null;
}
}

View File

@ -0,0 +1,32 @@
package com.upchina.group.constant;
// 消息类型1普通消息2推荐产品消息3进入交易圈消息4用户关注投顾消息5分享交易圈消息6开启互动消息7关闭互动消息; 8下单产品 9购物车产品数据量修改; 10购物车产品上架 11问卷12用户上下线13开启关闭企微二维码14购物车产品推送15取消推送产品16显示完整昵称17先审后发18开启私聊19显示圈子人数
public enum GroupMessageType {
NORMAL(1, "普通消息"),
RECOMMEND_PRODUCT(2, "推荐产品消息"),
ENTER_GROUP(3, "进入交易圈消息"),
USER_FOLLOW_ADVISOR(4, "用户关注投顾消息"),
SHARE_GROUP(5, "分享交易圈消息"),
OPEN_INTERACTIVE(6, "开启互动消息"),
CLOSE_INTERACTIVE(7, "关闭互动消息"),
ORDER_PRODUCT(8, "下单产品"),
CART_PRODUCT_COUNT_CHANGE(9, "购物车产品数据量修改"),
CART_PRODUCT_ON_SHELF(10, "购物车产品上架"),
QUESTION(11, "问卷"),
USER_ONLINE_OFFLINE(12, "用户上下线"),
OPEN_CLOSE_WECHAT_QRCODE(13, "开启、关闭企微二维码"),
CART_PRODUCT_PUSH(14, "购物车产品推送"),
CANCEL_PUSH_PRODUCT(15, "取消推送产品"),
SHOW_FULL_NICKNAME(16, "显示完整昵称"),
PRE_CHECK_SEND(17, "先审后发"),
OPEN_PRIVATE_CHAT(18, "开启私聊"),
SHOW_GROUP_MEMBER_COUNT(19, "显示圈子人数");
public final Integer value;
public final String desc;
GroupMessageType(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
}

View File

@ -0,0 +1,20 @@
package com.upchina.group.constant;
// 用户类型1投顾2用户3助教4运营人员
public enum GroupMessageUserType {
ADVISOR(1, "投顾"),
CUSTOMER(2, "用户"),
ASSISTANT(3, "助教"),
MANAGER(4, "运营"),
;
public final Integer value;
public final String name;
GroupMessageUserType(Integer value, String name) {
this.value = value;
this.name = name;
}
}

View File

@ -0,0 +1,32 @@
package com.upchina.group.constant;
//查询类型:1全部;2投顾;3用户;4精选
public enum QueryGroupMessageType {
ALL(1, "全部"),
ADVISOR(2, "投顾"),
CUSTOMER(3, "用户"),
SELECTED(4, "精选"),
PRIVATE(5, "私聊"),
;
public final Integer value;
public final String name;
QueryGroupMessageType(Integer value, String name) {
this.value = value;
this.name = name;
}
public static QueryGroupMessageType fromValue(Integer value) {
if (value == null) {
return null;
}
for (QueryGroupMessageType type : values()) {
if (type.value.equals(value)) {
return type;
}
}
return null;
}
}

View File

@ -26,7 +26,7 @@ import javax.annotation.Resource;
@Api(tags = "交易圈admin接口") @Api(tags = "交易圈admin接口")
@RestController @RestController
public class AdminGroupController { public class AdminGroupInfoController {
@Resource @Resource
private GroupInfoService groupInfoService; private GroupInfoService groupInfoService;

View File

@ -0,0 +1,102 @@
package com.upchina.group.controller.admin;
import com.upchina.common.handler.BizException;
import com.upchina.common.result.AppPager;
import com.upchina.common.result.CommonResult;
import com.upchina.common.result.ResponseStatus;
import com.upchina.common.vo.BackendUserVO;
import com.upchina.common.vo.OnlyIdVO;
import com.upchina.group.query.message.*;
import com.upchina.group.service.admin.AdminGroupMessageService;
import com.upchina.group.vo.message.GroupMessageVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "交易圈admin消息接口")
@RestController
public class AdminGroupMessageController {
@Resource
private AdminGroupMessageService adminGroupMessageService;
@ApiOperation("后台发送互动消息")
@PostMapping("/admin/group/message/sendAdvisorMessage")
public CommonResult<OnlyIdVO> sendAdvisorMessage(@Validated @RequestBody @ApiParam(required = true) SendGroupMessageAdminQuery query,
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUserVO) {
if (backendUserVO == null) {
throw new BizException(ResponseStatus.SESSION_EXPIRY);
}
OnlyIdVO vo = adminGroupMessageService.sendAdvisorMessage(query, backendUserVO);
return CommonResult.success(vo);
}
@ApiOperation("后台更新互动消息状态")
@PostMapping("/admin/group/message/updateStatus")
public CommonResult<Void> updateStatus(@Validated @RequestBody @ApiParam(required = true) UpdateGroupMessageStatusQuery query,
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUserVO) {
adminGroupMessageService.updateStatus(query, backendUserVO);
return CommonResult.success();
}
@ApiOperation("后台获取互动消息")
@PostMapping("/admin/group/message/getMessageList")
public CommonResult<AppPager<GroupMessageVO>> getMessageList(@Validated @RequestBody @ApiParam(required = true) ListGroupMessageQuery query,
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUserVO) {
AppPager<GroupMessageVO> list = adminGroupMessageService.getMessageList(query, backendUserVO);
return CommonResult.success(list);
}
@ApiOperation("后台推荐产品消息")
@PostMapping("/admin/group/message/sendProductMessage")
public CommonResult<OnlyIdVO> sendProductMessage(@Validated @RequestBody @ApiParam(required = true) GroupMessageProductQuery query,
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUserVO) {
if (backendUserVO == null) {
throw new BizException(ResponseStatus.SESSION_EXPIRY);
}
OnlyIdVO vo = adminGroupMessageService.saveProductMessage(query, backendUserVO);
return CommonResult.success(vo);
}
@ApiOperation("设置互动状态")
@PostMapping("/admin/group/message/setInteractiveStatus")
public CommonResult<Void> setInteractiveStatus(
@Validated @RequestBody @ApiParam(required = true) GroupMessageStatusQuery query,
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUser) {
if (backendUser == null) {
throw new BizException(ResponseStatus.SESSION_EXPIRY);
}
adminGroupMessageService.sendInteractiveStatusMessage(query, backendUser);
return CommonResult.success();
}
@ApiOperation("设置私聊状态")
@PostMapping("/admin/group/message/setPrivateStatus")
public CommonResult<Void> openPrivateChat(
@Validated @RequestBody @ApiParam(required = true) GroupMessageStatusQuery query,
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUser) {
if (backendUser == null) {
throw new BizException(ResponseStatus.SESSION_EXPIRY);
}
adminGroupMessageService.sendOpenPrivateChatMessage(query, backendUser);
return CommonResult.success();
}
@ApiOperation("设置显示圈子人数")
@PostMapping("/admin/group/message/setShowMemberCount")
public CommonResult<Void> showMemberCount(
@Validated @RequestBody @ApiParam(required = true) GroupMessageStatusQuery query,
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUser) {
if (backendUser == null) {
throw new BizException(ResponseStatus.SESSION_EXPIRY);
}
adminGroupMessageService.setShowMemberCount(query, backendUser);
return CommonResult.success();
}
}

View File

@ -20,7 +20,7 @@ import javax.annotation.Resource;
@Api(tags = "交易圈app接口") @Api(tags = "交易圈app接口")
@RestController @RestController
public class AppGroupController { public class AppGroupInfoController {
@Resource @Resource
private GroupInfoService groupInfoService; private GroupInfoService groupInfoService;

View File

@ -0,0 +1,51 @@
package com.upchina.group.controller.app;
import com.upchina.common.handler.BizException;
import com.upchina.common.result.AppPager;
import com.upchina.common.result.CommonResult;
import com.upchina.common.result.ResponseStatus;
import com.upchina.common.vo.FrontUserVO;
import com.upchina.group.query.message.ListGroupMessageAppQuery;
import com.upchina.group.query.message.SendGroupMessageAppQuery;
import com.upchina.group.service.app.AppGroupMessageService;
import com.upchina.group.vo.message.GroupMessageVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "交易圈app消息接口")
@RestController
public class AppGroupMessageController {
@Resource
private AppGroupMessageService appGroupMessageService;
@ApiOperation("APP获取交易圈互动消息")
@PostMapping("/app/group/message/getMessageList")
public CommonResult<AppPager<GroupMessageVO>> getMessageList(
@Validated @RequestBody @ApiParam(required = true) ListGroupMessageAppQuery query,
@RequestAttribute(value = "frontUser", required = false) FrontUserVO frontUserVO) {
AppPager<GroupMessageVO> list = appGroupMessageService.getMessageList(query, frontUserVO);
return CommonResult.success(list);
}
@ApiOperation("APP发送交易圈互动消息")
@PostMapping("/app/group/message/sendMessage")
public CommonResult<GroupMessageVO> sendMessage(
@Validated @RequestBody @ApiParam(required = true) SendGroupMessageAppQuery query,
@RequestAttribute(value = "frontUser", required = false) FrontUserVO frontUser) {
if (frontUser == null) {
throw new BizException(ResponseStatus.SESSION_EXPIRY);
}
GroupMessageVO vo = appGroupMessageService.sendMessage(query, frontUser);
return CommonResult.success(vo);
}
}

View File

@ -58,12 +58,24 @@ public class GroupInfo implements Serializable {
@TableField("welcome_message") @TableField("welcome_message")
private String welcomeMessage; private String welcomeMessage;
/**
* 互动状态 1:开启 2:关闭
*/
@TableField("interactive_status")
private Integer interactiveStatus;
/** /**
* 私聊状态 1:开启 2:关闭 * 私聊状态 1:开启 2:关闭
*/ */
@TableField("private_chat_status") @TableField("private_chat_status")
private Integer privateChatStatus; private Integer privateChatStatus;
/**
* 显示成员人数 1:开启 2:关闭
*/
@TableField("show_member_count")
private Integer showMemberCount;
/** /**
* 落地页ID * 落地页ID
*/ */
@ -225,6 +237,14 @@ public class GroupInfo implements Serializable {
public void setWelcomeMessage(String welcomeMessage) { public void setWelcomeMessage(String welcomeMessage) {
this.welcomeMessage = welcomeMessage; this.welcomeMessage = welcomeMessage;
} }
public Integer getInteractiveStatus() {
return interactiveStatus;
}
public void setInteractiveStatus(Integer interactiveStatus) {
this.interactiveStatus = interactiveStatus;
}
public Integer getPrivateChatStatus() { public Integer getPrivateChatStatus() {
return privateChatStatus; return privateChatStatus;
} }
@ -232,6 +252,13 @@ public class GroupInfo implements Serializable {
public void setPrivateChatStatus(Integer privateChatStatus) { public void setPrivateChatStatus(Integer privateChatStatus) {
this.privateChatStatus = privateChatStatus; this.privateChatStatus = privateChatStatus;
} }
public Integer getShowMemberCount() {
return showMemberCount;
}
public void setShowMemberCount(Integer showMemberCount) {
this.showMemberCount = showMemberCount;
}
public Integer getPageId() { public Integer getPageId() {
return pageId; return pageId;
} }

View File

@ -3,6 +3,7 @@ package com.upchina.group.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -36,7 +37,7 @@ public class GroupMessage implements Serializable {
private Integer groupId; private Integer groupId;
/** /**
* 交互类型1群聊2私聊 * 交互类型1群聊2私聊 3:会话消息
*/ */
@TableField("interactive_type") @TableField("interactive_type")
private Integer interactiveType; private Integer interactiveType;
@ -71,6 +72,12 @@ public class GroupMessage implements Serializable {
@TableField("user_name") @TableField("user_name")
private String userName; private String userName;
/**
* 私聊用户ID
*/
@TableField("private_user_id")
private String privateUserId;
/** /**
* 消息内容 * 消息内容
*/ */
@ -222,6 +229,13 @@ public class GroupMessage implements Serializable {
public void setUserName(String userName) { public void setUserName(String userName) {
this.userName = userName; this.userName = userName;
} }
public String getPrivateUserId() {
return privateUserId;
}
public void setPrivateUserId(String privateUserId) {
this.privateUserId = privateUserId;
}
public String getContent() { public String getContent() {
return content; return content;
} }

View File

@ -0,0 +1,48 @@
package com.upchina.group.query.message;
import com.upchina.common.vo.BackendUserVO;
import com.upchina.group.constant.GroupMessageStatus;
import com.upchina.group.entity.GroupMessage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;
@ApiModel("删除交易圈消息请求")
public class DeleteGroupMessageQuery {
@ApiModelProperty(value = "交易圈ID", required = true)
@NotNull(message = "交易圈ID不能为空")
private Integer groupId;
@ApiModelProperty(value = "消息ID列表", required = true)
@NotEmpty(message = "消息ID列表不能为空")
private List<Integer> ids;
public GroupMessage toPO(BackendUserVO userVO) {
GroupMessage message = new GroupMessage();
message.setStatus(GroupMessageStatus.DELETED.value);
message.setDeleteUserId(userVO.getUserId());
message.setDeleteTime(LocalDateTime.now());
return message;
}
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
}

View File

@ -0,0 +1,19 @@
package com.upchina.group.query.message;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
@ApiModel("关注投顾消息请求")
public class FollowAdvisorMessageQuery {
@NotNull(message = "交易圈ID不能为空")
@ApiModelProperty(value = "交易圈ID", required = true)
private Integer groupId;
@NotNull(message = "投顾ID不能为空")
@ApiModelProperty(value = "投顾ID", required = true)
private Integer advisorId;
}

View File

@ -0,0 +1,69 @@
package com.upchina.group.query.message;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@ApiModel("推荐产品消息请求")
public class GroupMessageProductQuery {
@ApiModelProperty(value = "交易圈ID", required = true)
@NotNull(message = "交易圈ID不能为空")
private Integer groupId;
@ApiModelProperty(value = "产品ID", required = true)
@NotNull(message = "产品ID不能为空")
private Integer productId;
@ApiModelProperty(value = "产品名称", required = true)
@NotBlank(message = "产品名称不能为空")
private String productName;
@ApiModelProperty(value = "产品描述")
private String productDesc;
@ApiModelProperty(value = "产品链接")
private String productUrl;
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductDesc() {
return productDesc;
}
public void setProductDesc(String productDesc) {
this.productDesc = productDesc;
}
public String getProductUrl() {
return productUrl;
}
public void setProductUrl(String productUrl) {
this.productUrl = productUrl;
}
}

View File

@ -0,0 +1,60 @@
package com.upchina.group.query.message;
import com.upchina.group.entity.GroupInfo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
@ApiModel("交易圈互动状态请求")
public class GroupMessageStatusQuery {
@NotNull(message = "交易圈ID不能为空")
@ApiModelProperty(value = "交易圈ID", required = true)
private Integer groupId;
@NotNull(message = "状态不能为空")
@ApiModelProperty(value = "状态 1:开启 2:关闭", required = true)
private Integer status;
public GroupInfo toInteractivePO() {
GroupInfo groupInfo = new GroupInfo();
groupInfo.setId(groupId);
groupInfo.setInteractiveStatus(status);
groupInfo.setUpdateTime(LocalDateTime.now());
return groupInfo;
}
public GroupInfo toPrivatePO() {
GroupInfo groupInfo = new GroupInfo();
groupInfo.setId(groupId);
groupInfo.setPrivateChatStatus(status);
groupInfo.setUpdateTime(LocalDateTime.now());
return groupInfo;
}
public GroupInfo toShowMemberCountPO() {
GroupInfo groupInfo = new GroupInfo();
groupInfo.setId(groupId);
groupInfo.setShowMemberCount(status);
groupInfo.setUpdateTime(LocalDateTime.now());
return groupInfo;
}
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
}

View File

@ -0,0 +1,55 @@
package com.upchina.group.query.message;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
@ApiModel("APP查询交易圈消息请求")
public class ListGroupMessageAppQuery {
@ApiModelProperty(value = "交易圈ID", required = true)
@NotNull(message = "交易圈ID不能为空")
private Integer groupId;
@ApiModelProperty("最后一条消息ID")
private Integer lastId;
@ApiModelProperty("查询类型:1全部;2投顾;3用户;4精选;5私聊")
private Integer type;
@ApiModelProperty("每页大小")
private Integer size = 20;
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public Integer getLastId() {
return lastId;
}
public void setLastId(Integer lastId) {
this.lastId = lastId;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
}

View File

@ -0,0 +1,66 @@
package com.upchina.group.query.message;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
@ApiModel("查询交易圈消息请求")
public class ListGroupMessageQuery {
@ApiModelProperty(value = "交易圈ID", required = true)
@NotNull(message = "交易圈ID不能为空")
private Integer groupId;
@ApiModelProperty("消息状态:1初始;2已审核;3已删除")
private Integer status;
@ApiModelProperty("查询类型:1全部;2投顾;3用户;4精选")
private Integer type;
@ApiModelProperty("最后一条消息ID")
private Integer lastId;
@ApiModelProperty("消息数量")
private Integer size;
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public Integer getLastId() {
return lastId;
}
public void setLastId(Integer lastId) {
this.lastId = lastId;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
}

View File

@ -0,0 +1,58 @@
package com.upchina.group.query.message;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@ApiModel("私聊消息列表查询请求")
public class ListPrivateMessageQuery {
@ApiModelProperty(value = "交易圈ID", required = true)
@NotNull(message = "交易圈ID不能为空")
private Integer groupId;
@ApiModelProperty(value = "对方用户ID", required = true)
@NotBlank(message = "对方用户ID不能为空")
private String toUserId;
@ApiModelProperty("最后一条消息ID")
private Integer lastId;
@ApiModelProperty("每页大小")
private Integer size = 20;
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public String getToUserId() {
return toUserId;
}
public void setToUserId(String toUserId) {
this.toUserId = toUserId;
}
public Integer getLastId() {
return lastId;
}
public void setLastId(Integer lastId) {
this.lastId = lastId;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
}

View File

@ -0,0 +1,50 @@
package com.upchina.group.query.message;
import com.upchina.common.vo.BackendUserVO;
import com.upchina.group.entity.GroupMessage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
@ApiModel("消息审核请求")
public class MessageAuditQuery {
@ApiModelProperty(value = "消息ID", required = true)
@NotNull(message = "消息ID不能为空")
private Integer messageId;
@ApiModelProperty(value = "审核状态:2已审核;", required = true)
@NotNull(message = "审核状态不能为空")
@Min(2)
@Max(2)
private Integer status;
public GroupMessage toPO(BackendUserVO backendUser) {
GroupMessage po = new GroupMessage();
po.setId(messageId);
po.setStatus(status);
po.setAuditUserId(backendUser.getUserId());
po.setAuditTime(LocalDateTime.now());
return po;
}
public Integer getMessageId() {
return messageId;
}
public void setMessageId(Integer messageId) {
this.messageId = messageId;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
}

View File

@ -0,0 +1,117 @@
package com.upchina.group.query.message;
import com.upchina.common.vo.BackendUserVO;
import com.upchina.group.constant.GroupInteractiveType;
import com.upchina.group.constant.GroupMessageContentType;
import com.upchina.group.constant.GroupMessageStatus;
import com.upchina.group.entity.GroupMessage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
@ApiModel("发送交易圈消息请求")
public class SendGroupMessageAdminQuery {
@ApiModelProperty(value = "交易圈ID", required = true)
@NotNull(message = "交易圈ID不能为空")
private Integer groupId;
@ApiModelProperty(value = "消息内容", required = true)
@NotBlank(message = "消息内容不能为空")
private String content;
@ApiModelProperty("回复消息ID")
private Integer replyId;
@ApiModelProperty("引用消息ID")
private Integer quoteId;
@ApiModelProperty("消息类型:1文本;2图片;3文件;4产品;5问卷")
@NotNull(message = "消息类型不能为空")
private Integer contentType = GroupMessageContentType.TEXT.value;
@ApiModelProperty("交互类型:1群聊;2私聊;3会话消息")
private Integer interactiveType;
@ApiModelProperty("接收用户ID(私聊)")
private String toUserId;
public GroupMessage toPO(BackendUserVO userVO) {
GroupMessage message = new GroupMessage();
message.setGroupId(groupId);
message.setContent(content);
message.setUserId(userVO.getUserId().toString());
message.setAdvisorId(userVO.getAdvisorId());
message.setUserName(userVO.getUserName());
message.setContentType(contentType);
message.setReplyId(replyId);
message.setQuoteId(quoteId);
message.setInteractiveType(interactiveType);
if (GroupInteractiveType.PRIVATE.value.equals(interactiveType)) {
message.setToUserId(toUserId);
message.setPrivateUserId(toUserId);
}
message.setStatus(GroupMessageStatus.INITIAL.value);
message.setCreateTime(LocalDateTime.now());
return message;
}
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Integer getReplyId() {
return replyId;
}
public void setReplyId(Integer replyId) {
this.replyId = replyId;
}
public Integer getQuoteId() {
return quoteId;
}
public void setQuoteId(Integer quoteId) {
this.quoteId = quoteId;
}
public Integer getContentType() {
return contentType;
}
public void setContentType(Integer contentType) {
this.contentType = contentType;
}
public Integer getInteractiveType() {
return interactiveType;
}
public void setInteractiveType(Integer interactiveType) {
this.interactiveType = interactiveType;
}
public String getToUserId() {
return toUserId;
}
public void setToUserId(String toUserId) {
this.toUserId = toUserId;
}
}

View File

@ -0,0 +1,70 @@
package com.upchina.group.query.message;
import com.upchina.common.vo.FrontUserVO;
import com.upchina.group.constant.GroupMessageContentType;
import com.upchina.group.constant.GroupMessageStatus;
import com.upchina.group.entity.GroupMessage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
@ApiModel("发送交易圈消息请求")
public class SendGroupMessageAppQuery {
@ApiModelProperty(value = "交易圈ID", required = true)
@NotNull(message = "交易圈ID不能为空")
private Integer groupId;
@ApiModelProperty(value = "消息内容", required = true)
@NotBlank(message = "消息内容不能为空")
private String content;
@ApiModelProperty("交互类型:1群聊;2私聊")
@Min(1)
@Max(2)
private Integer interactiveType;
public GroupMessage toPO(FrontUserVO userVO) {
GroupMessage message = new GroupMessage();
message.setGroupId(groupId);
message.setContent(content);
message.setUserId(userVO.getUserId());
message.setUserName(userVO.getUserName());
message.setContentType(GroupMessageContentType.TEXT.value);
message.setInteractiveType(interactiveType);
message.setPrivateUserId(userVO.getUserId());
message.setStatus(GroupMessageStatus.INITIAL.value);
message.setCreateTime(LocalDateTime.now());
return message;
}
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Integer getInteractiveType() {
return interactiveType;
}
public void setInteractiveType(Integer interactiveType) {
this.interactiveType = interactiveType;
}
}

View File

@ -0,0 +1,51 @@
package com.upchina.group.query.message;
import com.upchina.common.vo.BackendUserVO;
import com.upchina.group.constant.GroupMessageStatus;
import com.upchina.group.entity.GroupMessage;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
public class UpdateGroupMessageStatusQuery {
@ApiModelProperty(value = "消息ID", required = true)
@NotNull(message = "消息ID不能为空")
private Integer id;
@ApiModelProperty(value = "状态 1:初始 2:已审核 3:已删除", required = true)
@NotNull(message = "状态不能为空")
private Integer status;
public GroupMessage toPO(GroupMessageStatus targetStatus, BackendUserVO backendUserVO) {
GroupMessage groupMessage = new GroupMessage();
groupMessage.setId(id);
groupMessage.setStatus(targetStatus.value);
if (GroupMessageStatus.AUDITED.equals(targetStatus)) {
groupMessage.setAuditUserId(backendUserVO.getUserId());
groupMessage.setAuditTime(LocalDateTime.now());
} else if (GroupMessageStatus.DELETED.equals(targetStatus)) {
groupMessage.setDeleteUserId(backendUserVO.getUserId());
groupMessage.setDeleteTime(LocalDateTime.now());
}
return groupMessage;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
}

View File

@ -0,0 +1,19 @@
package com.upchina.group.query.message;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
@ApiModel("用户在线状态消息请求")
public class UserOnlineStatusMessageQuery {
@NotNull(message = "交易圈ID不能为空")
@ApiModelProperty(value = "交易圈ID", required = true)
private Integer groupId;
@NotNull(message = "在线状态不能为空")
@ApiModelProperty(value = "是否在线", required = true)
private Boolean online;
}

View File

@ -0,0 +1,172 @@
package com.upchina.group.service.admin;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.upchina.common.constant.IsOrNot;
import com.upchina.common.handler.BizException;
import com.upchina.common.result.AppPager;
import com.upchina.common.result.ResponseStatus;
import com.upchina.common.state.StateMachine;
import com.upchina.common.vo.BackendUserVO;
import com.upchina.common.vo.OnlyIdVO;
import com.upchina.group.constant.*;
import com.upchina.group.entity.GroupInfo;
import com.upchina.group.entity.GroupMessage;
import com.upchina.group.mapper.GroupInfoMapper;
import com.upchina.group.mapper.GroupMessageMapper;
import com.upchina.group.query.message.*;
import com.upchina.group.service.common.GroupCacheService;
import com.upchina.group.service.common.GroupMessageService;
import com.upchina.group.vo.message.GroupMessageVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class AdminGroupMessageService {
@Resource
private GroupMessageMapper groupMessageMapper;
@Resource
private GroupInfoMapper groupInfoMapper;
@Resource
private GroupMessageService groupMessageService;
@Resource
private GroupCacheService groupCacheService;
@Resource
private StateMachine<GroupMessageStatus> groupMessageSM;
@Transactional(rollbackFor = Exception.class)
public OnlyIdVO sendAdvisorMessage(SendGroupMessageAdminQuery query, BackendUserVO backendUser) {
GroupMessage message = query.toPO(backendUser);
groupMessageMapper.insert(message);
groupMessageService.publishGroupMessage(GroupMessageChannel.ALL, GroupMessageType.RECOMMEND_PRODUCT, query.getGroupId(), message.getContent());
return new OnlyIdVO(message.getId());
}
@Transactional(rollbackFor = Exception.class)
public void updateStatus(UpdateGroupMessageStatusQuery query, BackendUserVO backendUserVO) {
GroupMessage groupMessageInDB = groupMessageMapper.selectById(query.getId());
if (groupMessageInDB == null) {
throw new BizException(ResponseStatus.ID_NOT_EXIST_ERROR);
}
// 状态机扭转
GroupMessageStatus dbStatus = GroupMessageStatus.fromValue(groupMessageInDB.getStatus());
GroupMessageStatus targetStatus = groupMessageSM.send(dbStatus, GroupMessageStatus.fromValue(query.getStatus()));
GroupMessage groupMessage = query.toPO(targetStatus, backendUserVO);
groupMessageMapper.updateById(groupMessage);
groupCacheService.clearMessageCache(query.getId(), groupMessage.getGroupId());
}
public AppPager<GroupMessageVO> getMessageList(ListGroupMessageQuery query, BackendUserVO backendUser) {
Integer groupId = query.getGroupId();
Integer status = query.getStatus();
Integer type = query.getType();
Integer lastId = query.getLastId();
Integer size = query.getSize();
LambdaQueryWrapper<GroupMessage> wrapper = Wrappers.<GroupMessage>lambdaQuery()
.select(GroupMessage::getId)
.eq(GroupMessage::getGroupId, groupId)
.in(QueryGroupMessageType.ADVISOR.value.equals(type), GroupMessage::getUserType, GroupMessageUserType.ADVISOR.value, GroupMessageUserType.ASSISTANT.value)
.eq(QueryGroupMessageType.CUSTOMER.value.equals(type), GroupMessage::getUserType, GroupMessageUserType.CUSTOMER.value)
.eq(QueryGroupMessageType.SELECTED.value.equals(type), GroupMessage::getIsRecommend, IsOrNot.IS.value)
.eq(status != null, GroupMessage::getStatus, query.getStatus())
.lt(lastId != null, GroupMessage::getId, lastId)
.orderByDesc(GroupMessage::getId)
.last("limit " + (size + 1));
List<GroupMessage> list = groupMessageMapper.selectList(wrapper);
boolean hasNext = list.size() > size;
if (hasNext) {
list = list.subList(0, size);
}
List<GroupMessageVO> voList = list.stream().map(GroupMessage::getId).map(groupCacheService::getMessage).collect(Collectors.toList());
return new AppPager<>(voList, hasNext);
}
@Transactional(rollbackFor = Exception.class)
public OnlyIdVO saveProductMessage(GroupMessageProductQuery query, BackendUserVO backendUser) {
GroupMessage message = new GroupMessage();
message.setGroupId(query.getGroupId());
message.setContentType(GroupMessageContentType.PRODUCT.value);
message.setStatus(GroupMessageStatus.AUDITED.value);
message.setCreateUserId(backendUser.getUserId());
message.setCreateTime(LocalDateTime.now());
message.setAdvisorId(backendUser.getAdvisorId());
// 构建产品消息内容
JSONObject content = new JSONObject();
content.put("productId", query.getProductId());
content.put("productName", query.getProductName());
content.put("productDesc", query.getProductDesc());
content.put("productUrl", query.getProductUrl());
message.setContent(content.toJSONString());
groupMessageMapper.insert(message);
groupMessageService.publishGroupMessage(GroupMessageChannel.ALL, GroupMessageType.RECOMMEND_PRODUCT, query.getGroupId(), content);
return new OnlyIdVO(message.getId());
}
/**
* 发送开启/关闭互动消息
*/
public void sendInteractiveStatusMessage(GroupMessageStatusQuery query, BackendUserVO backendUser) {
Integer groupId = query.getGroupId();
GroupInfo groupInfo = groupInfoMapper.selectById(groupId);
if (groupInfo == null) {
throw new BizException(ResponseStatus.ID_NOT_EXIST_ERROR);
}
GroupInfo group = query.toInteractivePO();
groupInfoMapper.updateById(group);
groupMessageService.publishGroupMessage(GroupMessageChannel.APP, GroupMessageType.OPEN_INTERACTIVE, groupId, query.getStatus());
}
/**
* 发送开启私聊消息
*/
public void sendOpenPrivateChatMessage(GroupMessageStatusQuery query, BackendUserVO backendUser) {
Integer groupId = query.getGroupId();
GroupInfo groupInfo = groupInfoMapper.selectById(groupId);
if (groupInfo == null) {
throw new BizException(ResponseStatus.ID_NOT_EXIST_ERROR);
}
GroupInfo group = query.toPrivatePO();
groupInfoMapper.updateById(group);
groupMessageService.publishGroupMessage(GroupMessageChannel.APP, GroupMessageType.OPEN_PRIVATE_CHAT, groupId, query.getStatus());
}
/**
* 发送显示圈子人数消息
*/
public void setShowMemberCount(GroupMessageStatusQuery query, BackendUserVO backendUser) {
Integer groupId = query.getGroupId();
GroupInfo groupInfo = groupInfoMapper.selectById(groupId);
if (groupInfo == null) {
throw new BizException(ResponseStatus.ID_NOT_EXIST_ERROR);
}
GroupInfo group = query.toPrivatePO();
groupInfoMapper.updateById(group);
groupMessageService.publishGroupMessage(GroupMessageChannel.APP, GroupMessageType.SHOW_GROUP_MEMBER_COUNT, groupId, query.getStatus());
}
}

View File

@ -0,0 +1,151 @@
package com.upchina.group.service.app;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hazelcast.map.IMap;
import com.upchina.common.config.cache.CacheKey;
import com.upchina.common.constant.IsOrNot;
import com.upchina.common.handler.BizException;
import com.upchina.common.query.OnlyIdQuery;
import com.upchina.common.result.AppPager;
import com.upchina.common.result.ResponseStatus;
import com.upchina.common.service.CacheService;
import com.upchina.common.service.SensitiveWordService;
import com.upchina.common.util.TextUtil;
import com.upchina.common.vo.FrontUserVO;
import com.upchina.group.constant.GroupMessageChannel;
import com.upchina.group.constant.GroupMessageType;
import com.upchina.group.constant.GroupMessageUserType;
import com.upchina.group.constant.QueryGroupMessageType;
import com.upchina.group.entity.GroupMessage;
import com.upchina.group.mapper.GroupMessageMapper;
import com.upchina.group.query.message.ListGroupMessageAppQuery;
import com.upchina.group.query.message.SendGroupMessageAppQuery;
import com.upchina.group.service.GroupInfoService;
import com.upchina.group.service.admin.AdminGroupMessageService;
import com.upchina.group.service.common.GroupCacheService;
import com.upchina.group.service.common.GroupCommonService;
import com.upchina.group.service.common.GroupMessageService;
import com.upchina.group.vo.GroupVO;
import com.upchina.group.vo.message.GroupMessageVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;
@Service
public class AppGroupMessageService {
@Resource
private GroupMessageMapper groupMessageMapper;
@Resource
private GroupMessageService groupMessageService;
@Resource
private GroupInfoService groupInfoService;
@Resource
private GroupCacheService groupCacheService;
@Resource
private GroupCommonService groupCommonService;
@Resource
private SensitiveWordService sensitiveWordService;
@Resource
private AdminGroupMessageService adminGroupMessageService;
@Resource
private CacheService cacheService;
@Resource
private IMap<String, Object> groupCache;
public AppPager<GroupMessageVO> getMessageList(ListGroupMessageAppQuery query, FrontUserVO frontUser) {
Integer groupId = query.getGroupId();
Integer lastId = query.getLastId();
Integer type = query.getType();
Integer size = query.getSize();
GroupVO groupVO = groupInfoService.getForApp(new OnlyIdQuery(groupId), null);
if (groupVO == null) {
throw new BizException(ResponseStatus.ID_NOT_EXIST_ERROR, "交易圈不存在");
} else if (QueryGroupMessageType.PRIVATE.value.equals(type) && !IsOrNot.IS.value.equals(groupVO.getPrivateChatStatus())) {
throw new BizException(ResponseStatus.MESSAGE_PERMISSION_ERROR, "交易圈私聊未开启");
}
String userId = frontUser.getUserId();
// TODO 验证权限
groupCommonService.validateUserPermission(userId, groupVO);
QueryGroupMessageType msgType = QueryGroupMessageType.fromValue(type);
NavigableSet<Integer> sortedSet = this.getMsgIdSet(groupId, userId, msgType);
if (lastId != null && lastId != 0) {
sortedSet = sortedSet.tailSet(lastId, false);
}
List<GroupMessageVO> list = new ArrayList<>(size);
Iterator<Integer> it = sortedSet.iterator();
while (it.hasNext()) {
Integer msgId = it.next();
GroupMessageVO msg = groupCacheService.getMessage(msgId);
if (msg != null) {
list.add(msg);
if (--size == 0) break;
}
}
return new AppPager<>(list, it.hasNext());
}
private NavigableSet<Integer> getMsgIdSet(Integer groupId, String userId, QueryGroupMessageType msgType) {
if (QueryGroupMessageType.CUSTOMER.equals(msgType)) {
throw new BizException(ResponseStatus.PARM_ERROR, "查询类型错误");
}
String cacheKey = CacheKey.GroupKey.GROUP_MESSAGE_LIST + msgType.value;
if (QueryGroupMessageType.PRIVATE.equals(msgType)) {
cacheKey += "|" + userId;
}
return cacheService.get(groupCache, cacheKey, () -> {
LambdaQueryWrapper<GroupMessage> wrapper = Wrappers.<GroupMessage>lambdaQuery()
.select(GroupMessage::getId)
.eq(GroupMessage::getGroupId, groupId)
.in(QueryGroupMessageType.ADVISOR.equals(msgType), GroupMessage::getUserType, GroupMessageUserType.ADVISOR.value, GroupMessageUserType.ASSISTANT.value)
.eq(QueryGroupMessageType.CUSTOMER.equals(msgType), GroupMessage::getUserType, GroupMessageUserType.CUSTOMER.value)
.eq(QueryGroupMessageType.SELECTED.equals(msgType), GroupMessage::getIsRecommend, IsOrNot.IS.value)
.eq(QueryGroupMessageType.PRIVATE.equals(msgType), GroupMessage::getPrivateUserId, userId);
List<Object> objList = groupMessageMapper.selectObjs(wrapper);
NavigableSet<Integer> set = new TreeSet<>(Comparator.reverseOrder());
objList.stream().map(obj -> (Integer) obj).forEach(set::add);
return set;
});
}
@Transactional(rollbackFor = Exception.class)
public GroupMessageVO sendMessage(SendGroupMessageAppQuery query, FrontUserVO frontUser) {
Integer groupId = query.getGroupId();
String content = query.getContent();
// 敏感词检查
sensitiveWordService.check(content);
// 检查交易圈状态
if (!groupCommonService.checkGroupStatus(groupId)) {
throw new BizException(ResponseStatus.STATUS_ERROR, "交易圈未开启");
}
// 检查用户是否被禁言
if (groupCommonService.checkUserForbidden(frontUser.getUserId())) {
throw new BizException(ResponseStatus.COMMENT_BLACK_USER_ERROR, "您已被禁言");
}
GroupMessage message = query.toPO(frontUser);
message.setContent(TextUtil.cleanUnsafeHtml(content));
groupMessageMapper.insert(message);
GroupMessageVO vo = new GroupMessageVO(message);
groupMessageService.publishGroupMessage(GroupMessageChannel.ALL, GroupMessageType.NORMAL, groupId, vo);
return vo;
}
}

View File

@ -0,0 +1,44 @@
package com.upchina.group.service.common;
import com.hazelcast.map.IMap;
import com.upchina.common.config.cache.CacheKey;
import com.upchina.common.service.CacheService;
import com.upchina.group.entity.GroupMessage;
import com.upchina.group.mapper.GroupMessageMapper;
import com.upchina.group.vo.message.GroupMessageVO;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class GroupCacheService {
@Resource
private CacheService cacheService;
@Resource
private GroupMessageMapper groupMessageMapper;
@Resource
private IMap<String, Object> groupCache;
public void clearMessageCache(Integer msgId, Integer groupId) {
if (msgId != null) {
groupCache.remove(CacheKey.GroupKey.GROUP_MESSAGE_DETAIL + msgId);
}
if (groupId != null) {
groupCache.remove(CacheKey.GroupKey.GROUP_MESSAGE_LIST + groupId);
}
}
public GroupMessageVO getMessage(Integer messageId) {
return cacheService.get(groupCache,
CacheKey.GroupKey.GROUP_MESSAGE_DETAIL + messageId, () -> {
GroupMessage message = groupMessageMapper.selectById(messageId);
if (message == null) {
return null;
}
return new GroupMessageVO(message);
});
}
}

View File

@ -0,0 +1,31 @@
package com.upchina.group.service.common;
import com.upchina.group.constant.GroupInfoStatus;
import com.upchina.group.entity.GroupInfo;
import com.upchina.group.mapper.GroupInfoMapper;
import com.upchina.group.vo.GroupVO;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class GroupCommonService {
@Resource
private GroupInfoMapper groupInfoMapper;
public boolean checkGroupStatus(Integer groupId) {
GroupInfo group = groupInfoMapper.selectById(groupId);
return GroupInfoStatus.AUDITED.value.equals(group.getStatus());
}
public boolean checkUserForbidden(String userId) {
// 实现用户禁言检查逻辑
return false;
}
public boolean validateUserPermission(String userId, GroupVO groupVO) {
return true;
}
}

View File

@ -0,0 +1,127 @@
package com.upchina.group.service.common;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.topic.ITopic;
import com.upchina.common.config.cache.CacheKey;
import com.upchina.group.constant.GroupMessageChannel;
import com.upchina.group.constant.GroupMessageType;
import com.upchina.group.mapper.GroupMessageMapper;
import com.upchina.group.vo.message.GroupWsMessageVO;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
@Service
public class GroupMessageService {
@Resource
private GroupMessageMapper groupMessageMapper;
@Resource
private SimpMessagingTemplate simpMessagingTemplate;
@Resource
private HazelcastInstance hazelcastInstance;
public ITopic<GroupWsMessageVO<?>> adminGroupTopic = null;
public ITopic<GroupWsMessageVO<?>> adminPrivateTopic = null;
public ITopic<GroupWsMessageVO<?>> adminSessionTopic = null;
public ITopic<GroupWsMessageVO<?>> appGroupTopic = null;
public ITopic<GroupWsMessageVO<?>> appPrivateTopic = null;
public ITopic<GroupWsMessageVO<?>> appSessionTopic = null;
// 后端群组消息
public static final String ADMIN_GROUP_TOPIC = "/admin/group/topic";
// 后端私聊消息
public static final String ADMIN_PRIVATE_TOPIC = "/admin/private/topic";
// 后端用户消息
public static final String ADMIN_SESSION_TOPIC = "/admin/session/topic";
// APP端群组消息
public static final String APP_GROUP_TOPIC = "/app/group/topic";
// APP端私聊消息
public static final String APP_PRIVATE_TOPIC = "/app/private/topic";
// APP端个人消息
public static final String APP_SESSION_TOPIC = "/app/session/topic";
/**
* 启动时初始化Topic用于跨服务节点消息通信
*/
@PostConstruct
private void initVideoTopic() {
adminGroupTopic = initTopic(CacheKey.GroupMessageTopicKey.ADMIN_GROUP_TOPIC, ADMIN_GROUP_TOPIC, true, false, false);
adminPrivateTopic = initTopic(CacheKey.GroupMessageTopicKey.ADMIN_PRIVATE_TOPIC, ADMIN_PRIVATE_TOPIC, true, true, false);
adminSessionTopic = initTopic(CacheKey.GroupMessageTopicKey.ADMIN_SESSION_TOPIC, ADMIN_SESSION_TOPIC, false, true, true);
appGroupTopic = initTopic(CacheKey.GroupMessageTopicKey.APP_GROUP_TOPIC, APP_GROUP_TOPIC, true, false, false);
appPrivateTopic = initTopic(CacheKey.GroupMessageTopicKey.APP_PRIVATE_TOPIC, APP_PRIVATE_TOPIC, true, true, false);
appSessionTopic = initTopic(CacheKey.GroupMessageTopicKey.APP_SESSION_TOPIC, APP_SESSION_TOPIC, false, true, true);
}
/**
* 初始化Topic
*
* @param topicKey 主题Key
* @param subAddress 订阅地址
* @return 主题
*/
private ITopic<GroupWsMessageVO<?>> initTopic(String topicKey, String subAddress, boolean containGroupId, boolean containUserId, boolean containSessionId) {
ITopic<GroupWsMessageVO<?>> topic = hazelcastInstance.getTopic(topicKey);
topic.addMessageListener(message -> {
GroupWsMessageVO<?> payload = message.getMessageObject();
String destination = subAddress;
if (containGroupId) {
destination += "/" + payload.getGroupId();
}
if (containUserId) {
destination += "/" + payload.getUserId();
}
if (containSessionId) {
destination += "/" + payload.getSessionId();
}
simpMessagingTemplate.convertAndSend(destination, payload);
});
return topic;
}
public void publishGroupMessage(GroupMessageChannel channel, GroupMessageType messageType, Integer groupId, Object payload) {
GroupWsMessageVO<?> vo = GroupWsMessageVO.successGroupMsg(payload, groupId, messageType);
if (GroupMessageChannel.APP.equals(channel) || GroupMessageChannel.ALL.equals(channel)) {
appGroupTopic.publish(vo);
}
if (GroupMessageChannel.ADMIN.equals(channel) || GroupMessageChannel.ALL.equals(channel)) {
adminGroupTopic.publish(vo);
}
}
public void publishPrivateMessage(GroupMessageChannel channel, GroupMessageType messageType, Integer groupId, String userId, Object payload) {
GroupWsMessageVO<?> vo = GroupWsMessageVO.successPrivateMsg(payload, groupId, userId, messageType);
if (GroupMessageChannel.APP.equals(channel) || GroupMessageChannel.ALL.equals(channel)) {
appPrivateTopic.publish(vo);
}
if (GroupMessageChannel.ADMIN.equals(channel) || GroupMessageChannel.ALL.equals(channel)) {
adminPrivateTopic.publish(vo);
}
}
public void publishSessionMessage(GroupMessageChannel channel, GroupMessageType messageType, String userId, String sessionId, Object payload) {
GroupWsMessageVO<?> vo = GroupWsMessageVO.successSessionMsg(payload, userId, sessionId, messageType);
if (GroupMessageChannel.APP.equals(channel) || GroupMessageChannel.ALL.equals(channel)) {
appSessionTopic.publish(vo);
}
if (GroupMessageChannel.ADMIN.equals(channel) || GroupMessageChannel.ALL.equals(channel)) {
adminSessionTopic.publish(vo);
}
}
}

View File

@ -0,0 +1,220 @@
package com.upchina.group.vo.message;
import com.upchina.advisor.vo.AdvisorBasicVO;
import com.upchina.group.entity.GroupMessage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.time.LocalDateTime;
@ApiModel("交易圈消息VO")
public class GroupMessageVO {
@ApiModelProperty("消息ID")
private Integer id;
@ApiModelProperty("消息类型")
private Integer msgType;
@ApiModelProperty("交易圈ID")
private Integer groupId;
@ApiModelProperty("交互类型:1群聊;2私聊;3会话消息")
private Integer interactiveType;
@ApiModelProperty("用户类型")
private Integer userType;
@ApiModelProperty("用户ID")
private String userId;
@ApiModelProperty("用户名称")
private String userName;
@ApiModelProperty("消息内容")
private String content;
@ApiModelProperty("发布类型")
private Integer contentType;
@ApiModelProperty("回复消息ID")
private Integer replyId;
@ApiModelProperty("回复消息")
private GroupMessageVO replyMessage;
@ApiModelProperty("引用消息ID")
private Integer quoteId;
@ApiModelProperty("引用消息")
private GroupMessageVO quoteMessage;
@ApiModelProperty("状态")
private Integer status;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("投顾ID")
private Integer advisorId;
@ApiModelProperty("投顾")
private AdvisorBasicVO advisor;
public GroupMessageVO() {
}
public GroupMessageVO(GroupMessage message) {
this.id = message.getId();
this.msgType = message.getMsgType();
this.groupId = message.getGroupId();
this.interactiveType = message.getInteractiveType();
this.userType = message.getUserType();
this.userId = message.getUserId();
this.userName = message.getUserName();
this.content = message.getContent();
this.contentType = message.getContentType();
this.replyId = message.getReplyId();
this.quoteId = message.getQuoteId();
this.status = message.getStatus();
this.createTime = message.getCreateTime();
this.advisorId = message.getAdvisorId();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getMsgType() {
return msgType;
}
public void setMsgType(Integer msgType) {
this.msgType = msgType;
}
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public Integer getInteractiveType() {
return interactiveType;
}
public void setInteractiveType(Integer interactiveType) {
this.interactiveType = interactiveType;
}
public Integer getUserType() {
return userType;
}
public void setUserType(Integer userType) {
this.userType = userType;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Integer getContentType() {
return contentType;
}
public void setContentType(Integer contentType) {
this.contentType = contentType;
}
public Integer getReplyId() {
return replyId;
}
public void setReplyId(Integer replyId) {
this.replyId = replyId;
}
public GroupMessageVO getReplyMessage() {
return replyMessage;
}
public void setReplyMessage(GroupMessageVO replyMessage) {
this.replyMessage = replyMessage;
}
public Integer getQuoteId() {
return quoteId;
}
public void setQuoteId(Integer quoteId) {
this.quoteId = quoteId;
}
public GroupMessageVO getQuoteMessage() {
return quoteMessage;
}
public void setQuoteMessage(GroupMessageVO quoteMessage) {
this.quoteMessage = quoteMessage;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public Integer getAdvisorId() {
return advisorId;
}
public void setAdvisorId(Integer advisorId) {
this.advisorId = advisorId;
}
public AdvisorBasicVO getAdvisor() {
return advisor;
}
public void setAdvisor(AdvisorBasicVO advisor) {
this.advisor = advisor;
}
}

View File

@ -0,0 +1,13 @@
package com.upchina.group.vo.message;
public class GroupNotificationVO {
private Integer type;
private String content;
public GroupNotificationVO(Integer type, String content) {
this.type = type;
this.content = content;
}
// getters and setters
}

View File

@ -0,0 +1,154 @@
package com.upchina.group.vo.message;
import com.upchina.common.handler.BizException;
import com.upchina.common.result.ResponseStatus;
import com.upchina.common.util.RequestIdUtil;
import com.upchina.group.constant.GroupMessageType;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
public class GroupWsMessageVO<T> implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("状态码")
private Integer code;
@ApiModelProperty("状态详情")
private String message;
@ApiModelProperty("圈子ID")
private Integer groupId;
@ApiModelProperty("用户ID 属于私聊或个人消息时,该字段有值")
private String userId;
@ApiModelProperty("会话ID 属于个人消息时,该字段有值")
private String sessionId;
@ApiModelProperty("类型 1:查询在线人数 2:查询成员列表 3:查询历史消息 4:发送消息结果通知")
private Integer type;
@ApiModelProperty("数据体")
private T data;
@ApiModelProperty("序列号")
private String requestId;
public GroupWsMessageVO(Integer code, String message, Integer groupId, String userId, String sessionId, GroupMessageType type, T data) {
this.code = code;
this.message = message;
this.groupId = groupId;
this.userId = userId;
this.sessionId = sessionId;
this.type = type.value;
this.data = data;
this.requestId = RequestIdUtil.getValue();
}
public static <T> GroupWsMessageVO<T> successGroupMsg(T data, Integer groupId, GroupMessageType type) {
return new GroupWsMessageVO<>(ResponseStatus.OK.code, ResponseStatus.OK.message, groupId, null, null, type, data);
}
public static <T> GroupWsMessageVO<T> successPrivateMsg(T data, Integer groupId, String userId, GroupMessageType type) {
return new GroupWsMessageVO<>(ResponseStatus.OK.code, ResponseStatus.OK.message, groupId, userId, null, type, data);
}
public static <T> GroupWsMessageVO<T> successSessionMsg(T data, String userId, String sessionId, GroupMessageType type) {
return new GroupWsMessageVO<>(ResponseStatus.OK.code, ResponseStatus.OK.message, null, userId, sessionId, type, data);
}
public static <T> GroupWsMessageVO<T> errorSessionMsg(ResponseStatus status, String userId, String sessionId, GroupMessageType type) {
return new GroupWsMessageVO<>(status.code, status.message, null, userId, sessionId, type,null);
}
public static <T> GroupWsMessageVO<T> errorSessionMsg(BizException ex, String userId, String sessionId, GroupMessageType type) {
return new GroupWsMessageVO<>(ex.getErrorCode(), ex.getMessage(), null, userId, sessionId, type, null);
}
public static <T> GroupWsMessageVO<T> errorSessionMsg(Integer code, String message, String userId, String sessionId, GroupMessageType type) {
return new GroupWsMessageVO<>(code, message, null, userId, sessionId, type, null);
}
public boolean isSuccess() {
return ResponseStatus.OK.code.equals(this.code);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
@Override
public String toString() {
return "GroupWsMessageVO{" +
"code=" + code +
", message='" + message + '\'' +
", groupId=" + groupId +
", userId='" + userId + '\'' +
", sessionId='" + sessionId + '\'' +
", type=" + type +
", data=" + data +
", requestId='" + requestId + '\'' +
'}';
}
}

View File

@ -1,4 +1,4 @@
package com.taf.server.startup; package com.upchina.startup;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;

View File

@ -16,7 +16,7 @@ hazelcast:
taf: taf:
servant: servant:
advisorServant: DemoVideoDev.AdvisorServer.AdvisorObj@tcp -h 127.0.0.1 -t 60000 -p 45600 advisorServant: DemoVideoDev.AdvisorServer.AdvisorObj@tcp -h 127.0.0.1 -t 60000 -p 45600
scheduledEnable: true scheduledEnable: false
cron: cron:
saveVideoCount: "10 * * * * ?" #从cache刷新视频播放量到DB 每分钟的第10s执行 saveVideoCount: "10 * * * * ?" #从cache刷新视频播放量到DB 每分钟的第10s执行
refreshTranscodeStatus: "2 3/5 * * * ?" #从腾讯云拉取录播上传视频信息更新到DB refreshTranscodeStatus: "2 3/5 * * * ?" #从腾讯云拉取录播上传视频信息更新到DB

View File

@ -33,7 +33,7 @@ spring:
datasource: datasource:
master: master:
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.96.178.171:3306/advisor_video?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8 url: jdbc:mysql://47.96.178.171:3306/advisor_video?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8
username: eason username: eason
password: mysql2025easonzhu password: mysql2025easonzhu
mvc: mvc:

View File

@ -0,0 +1,192 @@
package com.upchina.group.service;
import com.hazelcast.map.IMap;
import com.upchina.advisor.entity.AdvisorBasic;
import com.upchina.advisor.service.AdvisorInfoService;
import com.upchina.common.query.OnlyIdQuery;
import com.upchina.common.service.AppUserService;
import com.upchina.common.service.CacheService;
import com.upchina.common.service.SensitiveWordService;
import com.upchina.common.state.StateMachine;
import com.upchina.common.vo.BackendUserVO;
import com.upchina.common.vo.InsertIdVO;
import com.upchina.course.service.PageService;
import com.upchina.group.constant.GroupInfoStatus;
import com.upchina.group.entity.GroupInfo;
import com.upchina.group.mapper.GroupInfoMapper;
import com.upchina.group.query.SaveGroupQuery;
import com.upchina.group.query.UpdateGroupQuery;
import com.upchina.group.query.UpdateGroupStatusQuery;
import com.upchina.rbac.entity.UserDept;
import com.upchina.rbac.service.AuthService;
import com.upchina.rbac.service.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class GroupInfoServiceTest {
@Mock
private GroupInfoMapper groupInfoMapper;
@Mock
private SensitiveWordService sensitiveWordService;
@Mock
private StateMachine<GroupInfoStatus> groupSM;
@Mock
private AdvisorInfoService advisorInfoService;
@Mock
private UserService userService;
@Mock
private AuthService authService;
@Mock
private PageService pageService;
@Mock
private CacheService cacheService;
@Mock
private AppUserService appUserService;
@Mock
private IMap<String, Object> groupCache;
@InjectMocks
private GroupInfoService groupInfoService;
private BackendUserVO mockBackendUser;
@BeforeEach
void setUp() {
mockBackendUser = new BackendUserVO();
mockBackendUser.setUserId(1);
mockBackendUser.setAdvisorId(100);
}
@Test
void save_ShouldSucceed() {
// 准备测试数据
SaveGroupQuery query = new SaveGroupQuery();
query.setName("测试群组");
query.setRemark("测试备注");
query.setDetail("测试详情");
query.setAdvisorId(100);
// 设置模拟行为
doNothing().when(sensitiveWordService).check(anyString(), anyString(), anyString());
when(groupInfoMapper.insert(any(GroupInfo.class))).thenReturn(1);
// 执行测试
InsertIdVO result = groupInfoService.save(query, mockBackendUser);
// 验证结果
assertNotNull(result);
verify(groupInfoMapper).insert(any(GroupInfo.class));
verify(sensitiveWordService).check(anyString(), anyString(), anyString());
}
@Test
void update_ShouldSucceed() {
// 准备测试数据
UpdateGroupQuery query = new UpdateGroupQuery();
query.setId(1);
query.setName("更新的群组名");
GroupInfo existingGroup = new GroupInfo();
existingGroup.setId(1);
existingGroup.setStatus(GroupInfoStatus.TO_COMMIT.value);
existingGroup.setAdvisorId(100);
// 设置模拟行为 - 修改这里的 mock 设置
when(groupInfoMapper.selectById(1)).thenReturn(existingGroup);
when(groupInfoMapper.updateById(any(GroupInfo.class))).thenReturn(1);
// 执行测试
groupInfoService.update(query, mockBackendUser);
// 验证结果
verify(groupInfoMapper).updateById(any(GroupInfo.class));
verify(groupCache).delete(anyString());
// 验证 sensitiveWordService.check 被调用使用参数捕获器
verify(sensitiveWordService).check(
eq("更新的群组名"), // 名称
isNull(), // 备注
isNull() // 详情
);
}
@Test
void updateStatus_ShouldSucceed() {
// 准备测试数据
UpdateGroupStatusQuery query = new UpdateGroupStatusQuery();
query.setId(1);
query.setEvent(GroupInfoStatus.EVENT_SUBMIT.value);
GroupInfo existingGroup = new GroupInfo();
existingGroup.setId(1);
existingGroup.setStatus(GroupInfoStatus.TO_AUDIT.value);
existingGroup.setAdvisorId(100);
// 设置模拟行为
when(groupInfoMapper.selectById(1)).thenReturn(existingGroup);
when(groupInfoMapper.updateById(any(GroupInfo.class))).thenReturn(1);
when(groupSM.send(any(), any())).thenReturn(GroupInfoStatus.TO_AUDIT);
// 执行测试
groupInfoService.updateStatus(query, mockBackendUser);
// 验证结果
verify(groupInfoMapper).updateById(any(GroupInfo.class));
verify(groupCache).delete(anyString());
}
@Test
void get_ShouldReturnGroupVO() {
// 准备测试数据
OnlyIdQuery query = new OnlyIdQuery(1);
GroupInfo groupInfo = new GroupInfo();
groupInfo.setId(1);
groupInfo.setAdvisorId(100);
Map<Integer, AdvisorBasic> advisorMap = new HashMap<>();
AdvisorBasic advisor = new AdvisorBasic();
advisor.setId(100);
advisorMap.put(100, advisor);
Map<Integer, UserDept> userMap = new HashMap<>();
UserDept userDept = new UserDept();
userDept.setUserId(1);
userDept.setName("测试用户");
userMap.put(1, userDept);
// 设置模拟行为
when(groupInfoMapper.selectById(1)).thenReturn(groupInfo);
when(advisorInfoService.getAdvisorMap()).thenReturn(advisorMap);
when(userService.getUserMap()).thenReturn(userMap);
// 执行测试
var result = groupInfoService.get(query, mockBackendUser);
// 验证结果
assertNotNull(result);
assertEquals(1, result.getId());
}
}

View File

@ -0,0 +1,134 @@
package com.upchina.group.service.admin;
import com.upchina.common.state.StateMachine;
import com.upchina.common.vo.BackendUserVO;
import com.upchina.common.vo.OnlyIdVO;
import com.upchina.group.constant.GroupMessageChannel;
import com.upchina.group.constant.GroupMessageStatus;
import com.upchina.group.constant.GroupMessageType;
import com.upchina.group.entity.GroupInfo;
import com.upchina.group.entity.GroupMessage;
import com.upchina.group.mapper.GroupInfoMapper;
import com.upchina.group.mapper.GroupMessageMapper;
import com.upchina.group.query.message.GroupMessageProductQuery;
import com.upchina.group.query.message.GroupMessageStatusQuery;
import com.upchina.group.query.message.SendGroupMessageAdminQuery;
import com.upchina.group.service.common.GroupCacheService;
import com.upchina.group.service.common.GroupMessageService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class AdminGroupMessageServiceTest {
@Mock
private GroupMessageMapper groupMessageMapper;
@Mock
private GroupInfoMapper groupInfoMapper;
@Mock
private GroupMessageService groupMessageService;
@Mock
private GroupCacheService groupCacheService;
@Mock
private StateMachine<GroupMessageStatus> groupMessageSM;
@InjectMocks
private AdminGroupMessageService adminGroupMessageService;
private BackendUserVO mockBackendUser;
@BeforeEach
void setUp() {
mockBackendUser = new BackendUserVO();
mockBackendUser.setUserId(1);
mockBackendUser.setAdvisorId(100);
}
@Test
void sendAdvisorMessage_ShouldSucceed() {
// 准备测试数据
SendGroupMessageAdminQuery query = new SendGroupMessageAdminQuery();
query.setGroupId(1);
query.setContent("测试消息");
when(groupMessageMapper.insert(any(GroupMessage.class))).thenReturn(1);
// 执行测试
OnlyIdVO result = adminGroupMessageService.sendAdvisorMessage(query, mockBackendUser);
// 验证结果
assertNotNull(result);
verify(groupMessageMapper).insert(any(GroupMessage.class));
verify(groupMessageService).publishGroupMessage(
eq(GroupMessageChannel.ALL),
eq(GroupMessageType.RECOMMEND_PRODUCT),
eq(query.getGroupId()),
any()
);
}
@Test
void sendInteractiveStatusMessage_ShouldSucceed() {
// 准备测试数据
GroupMessageStatusQuery query = new GroupMessageStatusQuery();
query.setGroupId(1);
query.setStatus(1);
GroupInfo mockGroupInfo = new GroupInfo();
mockGroupInfo.setId(1);
when(groupInfoMapper.selectById(query.getGroupId())).thenReturn(mockGroupInfo);
when(groupInfoMapper.updateById(any(GroupInfo.class))).thenReturn(1);
// 执行测试
adminGroupMessageService.sendInteractiveStatusMessage(query, mockBackendUser);
// 验证结果
verify(groupInfoMapper).selectById(query.getGroupId());
verify(groupInfoMapper).updateById(any(GroupInfo.class));
verify(groupMessageService).publishGroupMessage(
eq(GroupMessageChannel.APP),
eq(GroupMessageType.OPEN_INTERACTIVE),
eq(query.getGroupId()),
eq(query.getStatus())
);
}
@Test
void saveProductMessage_ShouldSucceed() {
// 准备测试数据
GroupMessageProductQuery query = new GroupMessageProductQuery();
query.setGroupId(1);
query.setProductId(100);
query.setProductName("测试产品");
query.setProductDesc("产品描述");
query.setProductUrl("http://example.com");
when(groupMessageMapper.insert(any(GroupMessage.class))).thenReturn(1);
// 执行测试
OnlyIdVO result = adminGroupMessageService.saveProductMessage(query, mockBackendUser);
// 验证结果
assertNotNull(result);
verify(groupMessageMapper).insert(any(GroupMessage.class));
verify(groupMessageService).publishGroupMessage(
eq(GroupMessageChannel.ALL),
eq(GroupMessageType.RECOMMEND_PRODUCT),
eq(query.getGroupId()),
any()
);
}
}

View File

@ -0,0 +1,215 @@
package com.upchina.group.service.app;
import com.hazelcast.map.IMap;
import com.upchina.common.constant.IsOrNot;
import com.upchina.common.handler.BizException;
import com.upchina.common.query.OnlyIdQuery;
import com.upchina.common.result.AppPager;
import com.upchina.common.service.CacheService;
import com.upchina.common.service.SensitiveWordService;
import com.upchina.common.vo.FrontUserVO;
import com.upchina.group.constant.GroupMessageChannel;
import com.upchina.group.constant.GroupMessageType;
import com.upchina.group.constant.QueryGroupMessageType;
import com.upchina.group.entity.GroupMessage;
import com.upchina.group.mapper.GroupMessageMapper;
import com.upchina.group.query.message.ListGroupMessageAppQuery;
import com.upchina.group.query.message.SendGroupMessageAppQuery;
import com.upchina.group.service.GroupInfoService;
import com.upchina.group.service.common.GroupCacheService;
import com.upchina.group.service.common.GroupCommonService;
import com.upchina.group.service.common.GroupMessageService;
import com.upchina.group.vo.GroupVO;
import com.upchina.group.vo.message.GroupMessageVO;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.NavigableSet;
import java.util.TreeSet;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class AppGroupMessageServiceTest {
@Mock
private GroupMessageMapper groupMessageMapper;
@Mock
private GroupMessageService groupMessageService;
@Mock
private GroupInfoService groupInfoService;
@Mock
private GroupCacheService groupCacheService;
@Mock
private GroupCommonService groupCommonService;
@Mock
private SensitiveWordService sensitiveWordService;
@Mock
private CacheService cacheService;
@Mock
private IMap<String, Object> groupCache;
@InjectMocks
private AppGroupMessageService appGroupMessageService;
private FrontUserVO mockFrontUser;
private GroupVO mockGroupVO;
@BeforeEach
void setUp() {
mockFrontUser = new FrontUserVO();
mockFrontUser.setUserId("123");
mockGroupVO = new GroupVO();
mockGroupVO.setId(1);
mockGroupVO.setPrivateChatStatus(IsOrNot.IS.value);
}
@Test
void getMessageList_ShouldSucceed() {
// 准备测试数据
ListGroupMessageAppQuery query = new ListGroupMessageAppQuery();
query.setGroupId(1);
query.setType(QueryGroupMessageType.ADVISOR.value);
query.setSize(10);
NavigableSet<Integer> mockSet = new TreeSet<>();
mockSet.add(1);
mockSet.add(2);
GroupMessageVO mockMessageVO = new GroupMessageVO();
mockMessageVO.setId(1);
// 设置模拟行为
when(groupInfoService.getForApp(any(OnlyIdQuery.class), any())).thenReturn(mockGroupVO);
when(groupCommonService.validateUserPermission(anyString(), any(GroupVO.class))).thenReturn(true);
when(cacheService.get(eq(groupCache), anyString(), any())).thenReturn(mockSet);
when(groupCacheService.getMessage(anyInt())).thenReturn(mockMessageVO);
// 执行测试
AppPager<GroupMessageVO> result = appGroupMessageService.getMessageList(query, mockFrontUser);
// 验证结果
assertNotNull(result);
assertFalse(result.getList().isEmpty());
assertEquals(1, result.getList().get(0).getId());
}
@Test
void getMessageList_WithPrivateType_ShouldSucceed() {
// 准备测试数据
ListGroupMessageAppQuery query = new ListGroupMessageAppQuery();
query.setGroupId(1);
query.setType(QueryGroupMessageType.PRIVATE.value);
query.setSize(10);
NavigableSet<Integer> mockSet = new TreeSet<>();
mockSet.add(1);
GroupMessageVO mockMessageVO = new GroupMessageVO();
mockMessageVO.setId(1);
// 设置模拟行为
when(groupInfoService.getForApp(any(OnlyIdQuery.class), any())).thenReturn(mockGroupVO);
when(groupCommonService.validateUserPermission(anyString(), any(GroupVO.class))).thenReturn(true);
when(cacheService.get(eq(groupCache), anyString(), any())).thenReturn(mockSet);
when(groupCacheService.getMessage(anyInt())).thenReturn(mockMessageVO);
// 执行测试
AppPager<GroupMessageVO> result = appGroupMessageService.getMessageList(query, mockFrontUser);
// 验证结果
assertNotNull(result);
assertFalse(result.getList().isEmpty());
}
@Test
void sendMessage_ShouldSucceed() {
// 准备测试数据
SendGroupMessageAppQuery query = new SendGroupMessageAppQuery();
query.setGroupId(1);
query.setContent("测试消息");
// 设置模拟行为
doNothing().when(sensitiveWordService).check(anyString());
when(groupCommonService.checkGroupStatus(anyInt())).thenReturn(true);
when(groupCommonService.checkUserForbidden(anyString())).thenReturn(false);
when(groupMessageMapper.insert(any(GroupMessage.class))).thenReturn(1);
// 执行测试
GroupMessageVO result = appGroupMessageService.sendMessage(query, mockFrontUser);
// 验证结果
assertNotNull(result);
verify(groupMessageService).publishGroupMessage(
eq(GroupMessageChannel.ALL),
eq(GroupMessageType.NORMAL),
eq(query.getGroupId()),
any(GroupMessageVO.class)
);
}
@Test
void sendMessage_WhenGroupClosed_ShouldThrowException() {
// 准备测试数据
SendGroupMessageAppQuery query = new SendGroupMessageAppQuery();
query.setGroupId(1);
query.setContent("测试消息");
// 设置模拟行为
doNothing().when(sensitiveWordService).check(anyString());
when(groupCommonService.checkGroupStatus(anyInt())).thenReturn(false);
// 执行测试并验证异常
assertThrows(BizException.class, () ->
appGroupMessageService.sendMessage(query, mockFrontUser)
);
}
@Test
void sendMessage_WhenUserForbidden_ShouldThrowException() {
// 准备测试数据
SendGroupMessageAppQuery query = new SendGroupMessageAppQuery();
query.setGroupId(1);
query.setContent("测试消息");
// 设置模拟行为
doNothing().when(sensitiveWordService).check(anyString());
when(groupCommonService.checkGroupStatus(anyInt())).thenReturn(true);
when(groupCommonService.checkUserForbidden(anyString())).thenReturn(true);
// 执行测试并验证异常
assertThrows(BizException.class, () ->
appGroupMessageService.sendMessage(query, mockFrontUser)
);
}
@Test
void getMessageList_WithInvalidGroup_ShouldThrowException() {
// 准备测试数据
ListGroupMessageAppQuery query = new ListGroupMessageAppQuery();
query.setGroupId(1);
query.setType(QueryGroupMessageType.ADVISOR.value);
// 设置模拟行为
when(groupInfoService.getForApp(any(OnlyIdQuery.class), any())).thenReturn(null);
// 执行测试并验证异常
assertThrows(BizException.class, () ->
appGroupMessageService.getMessageList(query, mockFrontUser)
);
}
}