1.前后端交互改版
2.艾特成员功能
3.用户名片卡功能
This commit is contained in:
zhongzb
2023-06-10 23:34:51 +08:00
parent cc6c69527b
commit 13dc04d4af
36 changed files with 604 additions and 87 deletions

View File

@@ -8,15 +8,8 @@ import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
import com.abin.mallchat.common.common.utils.RequestHolder;
import com.abin.mallchat.common.user.domain.enums.BlackTypeEnum;
import com.abin.mallchat.common.user.service.cache.UserCache;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageBaseReq;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageMarkReq;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessagePageReq;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq;
import com.abin.mallchat.custom.chat.domain.vo.request.msg.TextMsgReq;
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp;
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberStatisticResp;
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp;
import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp;
import com.abin.mallchat.custom.chat.domain.vo.request.*;
import com.abin.mallchat.custom.chat.domain.vo.response.*;
import com.abin.mallchat.custom.chat.service.ChatService;
import com.abin.mallchat.custom.user.service.impl.UserServiceImpl;
import io.swagger.annotations.Api;
@@ -27,7 +20,7 @@ import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.HashSet;
import java.util.Objects;
import java.util.List;
import java.util.Set;
/**
@@ -56,14 +49,20 @@ public class ChatController {
@GetMapping("/public/member/page")
@ApiOperation("群成员列表")
@FrequencyControl(time = 120, count = 10, target = FrequencyControl.Target.IP)
@FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
public ApiResult<CursorPageBaseResp<ChatMemberResp>> getMemberPage(@Valid CursorPageBaseReq request) {
black(request);
// black(request);
CursorPageBaseResp<ChatMemberResp> memberPage = chatService.getMemberPage(request);
filterBlackMember(memberPage);
return ApiResult.success(memberPage);
}
@GetMapping("/member/list")
@ApiOperation("房间内的所有群成员列表-@专用")
public ApiResult<List<ChatMemberListResp>> getMemberList(@Valid ChatMessageMemberReq chatMessageMemberReq) {
return ApiResult.success(chatService.getMemberList(chatMessageMemberReq));
}
private void filterBlackMember(CursorPageBaseResp<ChatMemberResp> memberPage) {
Set<String> blackMembers = getBlackUidSet();
memberPage.getList().removeIf(a -> blackMembers.contains(a.getUid().toString()));
@@ -84,9 +83,9 @@ public class ChatController {
@GetMapping("/public/msg/page")
@ApiOperation("消息列表")
@FrequencyControl(time = 120, count = 10, target = FrequencyControl.Target.IP)
@FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
public ApiResult<CursorPageBaseResp<ChatMessageResp>> getMsgPage(@Valid ChatMessagePageReq request) {
black(request);
// black(request);
CursorPageBaseResp<ChatMessageResp> msgPage = chatService.getMsgPage(request, RequestHolder.get().getUid());
filterBlackMsg(msgPage);
return ApiResult.success(msgPage);
@@ -113,10 +112,6 @@ public class ChatController {
@FrequencyControl(time = 30, count = 5, target = FrequencyControl.Target.UID)
@FrequencyControl(time = 60, count = 10, target = FrequencyControl.Target.UID)
public ApiResult<ChatMessageResp> sendMsg(@Valid @RequestBody ChatMessageReq request) {
if (Objects.isNull(request.getBody())) {
TextMsgReq req = new TextMsgReq(request.getContent(), request.getReplyMsgId());//todo 消息兼容之后删了
request.setBody(req);
}
Long msgId = chatService.sendMsg(request, RequestHolder.get().getUid());
//返回完整消息格式,方便前端展示
return ApiResult.success(chatService.getMsgResp(msgId, RequestHolder.get().getUid()));

View File

@@ -0,0 +1,24 @@
package com.abin.mallchat.custom.chat.domain.vo.request;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/**
* Description: 消息列表请求
* Author: <a href="https://github.com/zongzibinbin">abin</a>
* Date: 2023-03-29
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ChatMessageMemberReq {
@NotNull
@ApiModelProperty("会话id")
private Long roomId;
}

View File

@@ -30,11 +30,4 @@ public class ChatMessageReq {
@ApiModelProperty("消息内容类型不同传值不同见https://www.yuque.com/snab/mallcaht/rkb2uz5k1qqdmcmd")
private Object body;
@ApiModelProperty("消息内容")
@Deprecated
private String content;
@ApiModelProperty("回复的消息id,如果没有别传就好")
@Deprecated
private Long replyMsgId;
}

View File

@@ -6,6 +6,8 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* Description: 文本消息入参
* Author: <a href="https://github.com/zongzibinbin">abin</a>
@@ -22,4 +24,7 @@ public class TextMsgReq {
@ApiModelProperty("回复的消息id,如果没有别传就好")
private Long replyMsgId;
@ApiModelProperty("艾特的uid")
private List<Long> atUidList;
}

View File

@@ -0,0 +1,25 @@
package com.abin.mallchat.custom.chat.domain.vo.response;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Description: 群成员列表的成员信息
* Author: <a href="https://github.com/zongzibinbin">abin</a>
* Date: 2023-03-23
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ChatMemberListResp {
@ApiModelProperty("uid")
private Long uid;
@ApiModelProperty("用户名称")
private String name;
@ApiModelProperty("头像")
private String avatar;
}

View File

@@ -6,6 +6,7 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
/**
@@ -22,6 +23,8 @@ public class TextMsgResp {
private String content;
@ApiModelProperty("消息链接映射")
private Map<String, String> urlTitleMap;
@ApiModelProperty("艾特的uid")
private List<Long> atUidList;
@ApiModelProperty("父消息如果没有父消息返回的是null")
private TextMsgResp.ReplyMsg reply;

View File

@@ -3,16 +3,11 @@ package com.abin.mallchat.custom.chat.service;
import com.abin.mallchat.common.chat.domain.entity.Message;
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageBaseReq;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageMarkReq;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessagePageReq;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq;
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp;
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberStatisticResp;
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp;
import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp;
import com.abin.mallchat.custom.chat.domain.vo.request.*;
import com.abin.mallchat.custom.chat.domain.vo.response.*;
import javax.annotation.Nullable;
import java.util.List;
/**
* Description: 消息处理类
@@ -76,4 +71,6 @@ public interface ChatService {
void setMsgMark(Long uid, ChatMessageMarkReq request);
void recallMsg(Long uid, ChatMessageBaseReq request);
List<ChatMemberListResp> getMemberList(ChatMessageMemberReq chatMessageMemberReq);
}

View File

@@ -7,7 +7,6 @@ import com.abin.mallchat.common.chat.domain.entity.msg.MessageExtra;
import com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum;
import com.abin.mallchat.common.chat.domain.enums.MessageStatusEnum;
import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum;
import com.abin.mallchat.common.common.utils.discover.PrioritizedUrlTitleDiscover;
import com.abin.mallchat.common.user.domain.entity.IpDetail;
import com.abin.mallchat.common.user.domain.entity.IpInfo;
import com.abin.mallchat.common.user.domain.entity.ItemConfig;
@@ -27,7 +26,6 @@ import java.util.stream.Collectors;
*/
public class MessageAdapter {
public static final int CAN_CALLBACK_GAP_COUNT = 100;
private static final PrioritizedUrlTitleDiscover URL_TITLE_DISCOVER = new PrioritizedUrlTitleDiscover();
public static Message buildMsgSave(ChatMessageReq request, Long uid) {
@@ -35,16 +33,10 @@ public class MessageAdapter {
.fromUid(uid)
.roomId(request.getRoomId())
.status(MessageStatusEnum.NORMAL.getStatus())
.extra(buildExtra(request))
.build();
}
private static MessageExtra buildExtra(ChatMessageReq request) {
Map<String, String> contentTitleMap = URL_TITLE_DISCOVER.getContentTitleMap(request.getContent());
return MessageExtra.builder().urlTitleMap(contentTitleMap).build();
}
public static List<ChatMessageResp> buildMsgResp(List<Message> messages, Map<Long, Message> replyMap, Map<Long, User> userMap, List<MessageMark> msgMark, Long receiveUid, Map<Long, ItemConfig> itemMap) {
Map<Long, List<MessageMark>> markMap = msgMark.stream().collect(Collectors.groupingBy(MessageMark::getMsgId));
return messages.stream().map(a -> {

View File

@@ -26,14 +26,8 @@ import com.abin.mallchat.common.user.domain.enums.RoleEnum;
import com.abin.mallchat.common.user.service.IRoleService;
import com.abin.mallchat.common.user.service.cache.ItemCache;
import com.abin.mallchat.common.user.service.cache.UserCache;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageBaseReq;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageMarkReq;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessagePageReq;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq;
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp;
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberStatisticResp;
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp;
import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp;
import com.abin.mallchat.custom.chat.domain.vo.request.*;
import com.abin.mallchat.custom.chat.domain.vo.response.*;
import com.abin.mallchat.custom.chat.service.ChatService;
import com.abin.mallchat.custom.chat.service.adapter.MemberAdapter;
import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter;
@@ -45,7 +39,9 @@ import com.abin.mallchat.custom.chat.service.strategy.msg.AbstractMsgHandler;
import com.abin.mallchat.custom.chat.service.strategy.msg.MsgHandlerFactory;
import com.abin.mallchat.custom.chat.service.strategy.msg.RecallMsgHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -92,7 +88,7 @@ public class ChatServiceImpl implements ChatService {
@Transactional
public Long sendMsg(ChatMessageReq request, Long uid) {
AbstractMsgHandler msgHandler = MsgHandlerFactory.getStrategyNoNull(request.getMsgType());//todo 这里先不扩展,后续再改
msgHandler.checkMsg(request);
msgHandler.checkMsg(request, uid);
//同步获取消息的跳转链接标题
Message insert = MessageAdapter.buildMsgSave(request, uid);
messageDao.save(insert);
@@ -196,6 +192,22 @@ public class ChatServiceImpl implements ChatService {
recallMsgHandler.recall(uid, message);
}
@Override
@Cacheable(cacheNames = "member", key = "'memberList.'+#req.roomId")
public List<ChatMemberListResp> getMemberList(ChatMessageMemberReq req) {
if (Objects.equals(1L, req.getRoomId())) {//大群聊可看见所有人
return userDao.getMemberList()
.stream()
.map(a -> {
ChatMemberListResp resp = new ChatMemberListResp();
BeanUtils.copyProperties(a, resp);
resp.setUid(a.getId());
return resp;
}).collect(Collectors.toList());
}
return null;
}
private void checkRecall(Long uid, Message message) {
AssertUtil.isNotEmpty(message, "消息有误");
AssertUtil.notEqual(message.getType(), MessageTypeEnum.RECALL, "消息无法撤回");

View File

@@ -20,7 +20,7 @@ public abstract class AbstractMsgHandler {
abstract MessageTypeEnum getMsgTypeEnum();
public abstract void checkMsg(ChatMessageReq req);
public abstract void checkMsg(ChatMessageReq req, Long uid);
public abstract void saveMsg(Message msg, ChatMessageReq req);

View File

@@ -40,7 +40,7 @@ public class RecallMsgHandler extends AbstractMsgHandler {
}
@Override
public void checkMsg(ChatMessageReq request) {
public void checkMsg(ChatMessageReq request, Long uid) {
throw new UnsupportedOperationException();
}

View File

@@ -9,15 +9,22 @@ import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum;
import com.abin.mallchat.common.chat.service.cache.MsgCache;
import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum;
import com.abin.mallchat.common.common.utils.AssertUtil;
import com.abin.mallchat.common.common.utils.discover.PrioritizedUrlTitleDiscover;
import com.abin.mallchat.common.user.domain.entity.User;
import com.abin.mallchat.common.user.domain.enums.RoleEnum;
import com.abin.mallchat.common.user.service.IRoleService;
import com.abin.mallchat.common.user.service.cache.UserCache;
import com.abin.mallchat.common.user.service.cache.UserInfoCache;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq;
import com.abin.mallchat.custom.chat.domain.vo.request.msg.TextMsgReq;
import com.abin.mallchat.custom.chat.domain.vo.response.msg.TextMsgResp;
import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@@ -34,6 +41,12 @@ public class TextMsgHandler extends AbstractMsgHandler {
private MsgCache msgCache;
@Autowired
private UserCache userCache;
@Autowired
private UserInfoCache userInfoCache;
@Autowired
private IRoleService iRoleService;
@Autowired
private static final PrioritizedUrlTitleDiscover URL_TITLE_DISCOVER = new PrioritizedUrlTitleDiscover();
@Override
MessageTypeEnum getMsgTypeEnum() {
@@ -41,7 +54,7 @@ public class TextMsgHandler extends AbstractMsgHandler {
}
@Override
public void checkMsg(ChatMessageReq request) {
public void checkMsg(ChatMessageReq request, Long uid) {
TextMsgReq body = BeanUtil.toBean(request.getBody(), TextMsgReq.class);
AssertUtil.isNotEmpty(body.getContent(), "内容不能为空");
AssertUtil.isTrue(body.getContent().length() < 500, "消息内容过长服务器扛不住啊兄dei");
@@ -51,14 +64,26 @@ public class TextMsgHandler extends AbstractMsgHandler {
AssertUtil.isNotEmpty(replyMsg, "回复消息不存在");
AssertUtil.equal(replyMsg.getRoomId(), request.getRoomId(), "只能回复相同会话内的消息");
}
if (CollectionUtils.isNotEmpty(body.getAtUidList())) {
AssertUtil.isTrue(body.getAtUidList().size() > 10, "一次别艾特这么多人");
List<Long> atUidList = body.getAtUidList();
Map<Long, User> batch = userInfoCache.getBatch(atUidList);
AssertUtil.equal(atUidList.size(), batch.values().size(), "@用户不存在");
boolean atAll = body.getAtUidList().contains(0L);
if (atAll) {
AssertUtil.isTrue(iRoleService.hasPower(uid, RoleEnum.CHAT_MANAGER), "没有权限");
}
}
}
@Override
public void saveMsg(Message msg, ChatMessageReq request) {//插入文本内容
TextMsgReq body = BeanUtil.toBean(request.getBody(), TextMsgReq.class);
MessageExtra extra = Optional.ofNullable(msg.getExtra()).orElse(new MessageExtra());
Message update = new Message();
update.setId(msg.getId());
update.setContent(body.getContent());
update.setExtra(extra);
//如果有回复消息
if (Objects.nonNull(body.getReplyMsgId())) {
Integer gapCount = messageDao.getGapCount(request.getRoomId(), body.getReplyMsgId(), msg.getId());
@@ -66,6 +91,15 @@ public class TextMsgHandler extends AbstractMsgHandler {
update.setReplyMsgId(body.getReplyMsgId());
}
//判断消息url跳转
Map<String, String> urlTitleMap = URL_TITLE_DISCOVER.getContentTitleMap(body.getContent());
extra.setUrlTitleMap(urlTitleMap);
//艾特功能
if (CollectionUtils.isNotEmpty(body.getAtUidList())) {
extra.setAtUidList(body.getAtUidList());
}
messageDao.updateById(update);
}
@@ -74,6 +108,7 @@ public class TextMsgHandler extends AbstractMsgHandler {
TextMsgResp resp = new TextMsgResp();
resp.setContent(msg.getContent());
resp.setUrlTitleMap(Optional.ofNullable(msg.getExtra()).map(MessageExtra::getUrlTitleMap).orElse(null));
resp.setAtUidList(Optional.ofNullable(msg.getExtra()).map(MessageExtra::getAtUidList).orElse(null));
//回复消息
Optional<Message> reply = Optional.ofNullable(msg.getReplyMsgId())
.map(msgCache::getMsg)