feat:聊天会员限制

This commit is contained in:
dzc committed 2025-11-29 13:44:31 +08:00
1 parent b24ed26504
commit 13cdff58bb
9 files changed
+180 -27

No files matched your search

@@ -80,4 +80,8 @@ public interface MemberErrorCode {
//========== 会员开通类型 1-004-017-000 ==========
ErrorCode FEEDBACK_NOT_EXISTS = new ErrorCode(1_004_017_000, "反馈不存在");
//========== 聊天相关 1-004-018-000 ==========
ErrorCode CHAT_USER_COUNT_EXCEED = new ErrorCode(1_004_018_000, "当天免费聊天人数已用完");
ErrorCode CHAT_MSG_COUNT_EXCEED = new ErrorCode(1_004_018_001, "当天免费聊天次数已用完");
}
@@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.member.client.service;
import cn.iocoder.yudao.module.member.client.vo.chat.ChatTableRespVO;
import cn.iocoder.yudao.module.member.client.vo.chat.friend.ChatAddFriendReqVo;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateMessageCountReqVO;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateMessageInfoReqVO;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateMessageReqVO;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateMessageRespVO;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.*;
import cn.iocoder.yudao.module.member.client.vo.chat.sensitive.*;
import cn.iocoder.yudao.module.member.client.vo.chat.user.*;
@@ -85,6 +82,11 @@ public interface ChatApi {
*/
List<Map> privateCount(ChatPrivateMessageCountReqVO dto);
/**
* 私聊消息发送消息的统计
*/
List<ChatPrivateTotalMessageTotalResVo> privateTotal(ChatPrivateTotalMessageTotalReqVo dto);
/* *************************************** end 私聊 end *************************************** */
}
@@ -8,10 +8,7 @@ import cn.iocoder.yudao.module.member.client.tool.ChatApiTool;
import cn.iocoder.yudao.module.member.client.vo.chat.ChatBaseRespVo;
import cn.iocoder.yudao.module.member.client.vo.chat.ChatTableRespVO;
import cn.iocoder.yudao.module.member.client.vo.chat.friend.ChatAddFriendReqVo;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateMessageCountReqVO;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateMessageInfoReqVO;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateMessageReqVO;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateMessageRespVO;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.*;
import cn.iocoder.yudao.module.member.client.vo.chat.sensitive.*;
import cn.iocoder.yudao.module.member.client.vo.chat.user.*;
import cn.iocoder.yudao.module.member.framework.web.config.ChatProperties;
@@ -415,7 +412,7 @@ public class ChatApiImpl implements ChatApi {
log.error("私聊消息统计,返回json解析错误");
return null;
}
return null;
return vo;
} catch (Exception e) {
e.printStackTrace();
log.error("私聊消息统计,意外的错误", e);
@@ -423,6 +420,38 @@ public class ChatApiImpl implements ChatApi {
}
}
/**
* 私聊消息发送消息的统计
*/
@Override
public List<ChatPrivateTotalMessageTotalResVo> privateTotal(ChatPrivateTotalMessageTotalReqVo dto) {
ChatApiTool.API api = setApiConfig(ChatApiTool.PRIVATE_MSG_TOTAL);
try {
String body = JSONUtil.toJsonStr(dto);
String res = HttpRequest.post(api.getFullPath()).header(apiCountersign(body)).body(body).execute().body();
log.debug("私聊消息发送消息的统计,res:{}", res);
if (ObjectUtil.isEmpty(res)) {
log.error("私聊消息发送消息的统计,res为空");
return null;
}
ChatBaseRespVo baseRes = JSONUtil.toBean(res, ChatBaseRespVo.class);
if (ObjectUtil.isEmpty(baseRes) || !baseRes.isSuccess()) {
log.error("私聊消息发送消息的统计,返回错误");
return null;
}
List<ChatPrivateTotalMessageTotalResVo> vo = JSONUtil.toList(baseRes.getData(), ChatPrivateTotalMessageTotalResVo.class);
if (ObjectUtil.isEmpty(vo)) {
log.error("私聊消息发送消息的统计,返回json解析错误");
return null;
}
return vo;
} catch (Exception e) {
e.printStackTrace();
log.error("私聊消息发送消息的统计,意外的错误", e);
return null;
}
}
/* *************************************** end 私聊 end *************************************** */
private ChatApiTool.API setApiConfig(ChatApiTool.API api) {
@@ -29,6 +29,7 @@ public class ChatApiTool {
public static final API PRIVATE_MSG_PAGE = API.builder().summary("私聊分页").url("/third/privateMsg/page").method(HttpMethod.POST).build();
public static final API PRIVATE_MSG_INFO = API.builder().summary("私聊详情").url("/third/privateMsg/getById").method(HttpMethod.POST).build();
public static final API PRIVATE_MSG_COUNT = API.builder().summary("私聊统计").url("/third/privateMsg/dailyCount").method(HttpMethod.POST).build();
public static final API PRIVATE_MSG_TOTAL = API.builder().summary("私聊消息发送消息的统计").url("/third/privateMsg/total").method(HttpMethod.POST).build();
// 敏感词
public static final API SENSITIVE_PAGE = API.builder().summary("敏感词分页").url("/third/sensitive/page").method(HttpMethod.POST).build();
@@ -0,0 +1,26 @@
package cn.iocoder.yudao.module.member.client.vo.chat.privatemsg;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class ChatPrivateTotalMessageTotalReqVo {
/**
* 发送人id
*/
private Long sendId;
/**
* 接收人id
*/
private Long receiveId;
/**
* 发送时间范围
*/
private LocalDateTime[] timeRange;
}
@@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.member.client.vo.chat.privatemsg;
import lombok.Data;
@Data
public class ChatPrivateTotalMessageTotalResVo {
/**
* 发送者id
*/
private Long sendId;
/**
* 发送名
*/
private String sendName;
/**
* 接受者id
*/
private Long receiveId;
/**
* 接收者名称
*/
private String receiveName;
/**
* 消息总数
*/
private Long messageTotal;
}
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.member.client.service.ChatApi;
import cn.iocoder.yudao.module.member.client.vo.chat.friend.ChatAddFriendReqVo;
import cn.iocoder.yudao.module.member.client.vo.chat.user.ChatPrivateMessageSendReqVO;
import cn.iocoder.yudao.module.member.client.vo.chat.user.ChatPrivateMessageSendResVO;
import cn.iocoder.yudao.module.member.service.opentype.OpenTypeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
@@ -21,13 +22,18 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
@Validated
public class AppChatController {
@Resource
private OpenTypeService openTypeService;
@Resource
private ChatApi chatApi;
@GetMapping("/send-private-msg")
@Operation(summary = "创建用户反馈")
public CommonResult<ChatPrivateMessageSendResVO> sendPrivateMsg(@RequestBody ChatPrivateMessageSendReqVO body) {
body.setSendId(getLoginUserId());
Long sendId = getLoginUserId();
openTypeService.isUserCanSendMessage(sendId, body.getRecvId());
body.setSendId(sendId);
body.setTerminal(1);
return success(chatApi.send(body));
}
@@ -49,8 +49,18 @@ public interface OpenTypeService {
*/
Long payOpenType(AppPayOpenReqType dto);
/**
* 当前用户是否是会员
*/
boolean isUserOpenType(Long memberId);
/**
* 当前用户是否是会员
*/
boolean isUserOpenType();
/**
* 判断用户是否还可以发送消息
*/
boolean isUserCanSendMessage(Long userId);
boolean isUserCanSendMessage(Long sendId, Long receiveId);
}
@@ -6,12 +6,16 @@ import cn.iocoder.yudao.module.member.client.service.ChatApi;
import cn.iocoder.yudao.module.member.client.vo.chat.ChatTableRespVO;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateMessageReqVO;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateMessageRespVO;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateTotalMessageTotalReqVo;
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateTotalMessageTotalResVo;
import cn.iocoder.yudao.module.member.controller.app.opentype.vo.AppPayOpenReqType;
import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO;
import cn.iocoder.yudao.module.member.dal.dataobject.opentype.OpenTypeUserDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.opentype.OpenTypeUserMapper;
import cn.iocoder.yudao.module.member.enums.MemberErrorCode;
import cn.iocoder.yudao.module.member.enums.opentype.OpenTypeUserStatusEnum;
import cn.iocoder.yudao.module.member.service.config.MemberConfigService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -37,6 +41,7 @@ import java.util.Date;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
/**
* 会员类型 Service 实现类
@@ -53,6 +58,9 @@ public class OpenTypeServiceImpl implements OpenTypeService {
@Resource
private OpenTypeUserMapper openTypeUserMapper;
@Resource
private MemberConfigService memberConfigService;
@Resource
private ChatApi chatApi;
@@ -147,29 +155,63 @@ public class OpenTypeServiceImpl implements OpenTypeService {
return openTypeUserObj.getId();
}
/**
* 当前用户是否是会员
*/
@Override
public boolean isUserOpenType(Long memberId) {
OpenTypeUserDO openTypeUserDO = openTypeUserMapper.selectEnableByUserId(memberId);
return ObjectUtil.isNotEmpty(openTypeUserDO);
}
/**
* 当前用户是否是会员
*/
@Override
public boolean isUserOpenType() {
return isUserOpenType(getLoginUserId());
}
/**
* 判断用户是否还可以发送消息
*/
@Override
public boolean isUserCanSendMessage(Long userId) {
public boolean isUserCanSendMessage(Long sendId, Long receiveId) {
// 判断是否是会员
if (isUserOpenType(sendId)) return true;
// 获取配置
MemberConfigDO config = memberConfigService.getConfig();
// 普通用户每天可以和几个人聊天
Integer defaultChatUserCout = config.getDefaultChatUserCout();
if (ObjectUtil.isEmpty(defaultChatUserCout)) defaultChatUserCout = 3;
// 普通用户每天可以和人发几次消息
Integer defaultChatUserMsgCout = config.getDefaultChatUserMsgCout();
if (ObjectUtil.isEmpty(defaultChatUserMsgCout)) defaultChatUserMsgCout = 3;
LocalDateTime now = LocalDateTime.now();
LocalDateTime startDate = now.withHour(0).withMinute(0).withSecond(0);
LocalDateTime endDate = now.withHour(23).withMinute(59).withSecond(59);
Date startDate = Date.from(now.withHour(0).withMinute(0).withSecond(0).atZone(ZoneId.systemDefault()).toInstant());
Date endDate = Date.from(now.withHour(23).withMinute(59).withSecond(59).atZone(ZoneId.systemDefault()).toInstant());
ChatPrivateMessageReqVO dto = new ChatPrivateMessageReqVO();
dto.setPageNum(1);
dto.setPageSize(100);
dto.setSendId(userId);
dto.setSendTimeList(new ArrayList<Date>() {{
add(startDate);
add(endDate);
}});
ChatPrivateTotalMessageTotalReqVo dto = new ChatPrivateTotalMessageTotalReqVo();
dto.setSendId(sendId);
dto.setTimeRange(new LocalDateTime[]{
startDate,
endDate
});
try {
ChatTableRespVO<ChatPrivateMessageRespVO> page = chatApi.privateMsgPage(dto);
if (ObjectUtil.isEmpty(page) || ObjectUtil.isEmpty(page.getRows())) return true;
List<ChatPrivateMessageRespVO> rows = page.getRows();
List<ChatPrivateTotalMessageTotalResVo> msgList = chatApi.privateTotal(dto);
if (ObjectUtil.isEmpty(msgList)) return true;
// 普通用户聊天人数是否超过上限
if (msgList.size() > defaultChatUserCout) {
throw exception(MemberErrorCode.CHAT_USER_COUNT_EXCEED);
}
// 聊天人数已经超过限制
ChatPrivateTotalMessageTotalResVo targetCount = msgList.stream().filter(item -> ObjectUtil.equals(item.getSendId(), sendId) && ObjectUtil.equals(item.getReceiveId(), receiveId)).findFirst().orElse(null);
if (ObjectUtil.isEmpty(targetCount)) return true;
if (targetCount.getMessageTotal() > defaultChatUserMsgCout) {
throw exception(MemberErrorCode.CHAT_MSG_COUNT_EXCEED);
}
return true;
} catch (Exception e) {
e.printStackTrace();
log.error("|判断用户是否还可以发送消息|意外的错误:{}", e.getMessage());