mirror of
https://github.com/zongzibinbin/MallChat.git
synced 2026-03-14 06:03:42 +08:00
1.记录微信消息
2.重复上线问题解决
This commit is contained in:
@@ -85,7 +85,7 @@ public class ChatMessageResp {
|
||||
private Integer userDislike;
|
||||
}
|
||||
@Data
|
||||
private static class Badge {
|
||||
public static class Badge {
|
||||
@ApiModelProperty("徽章图像")
|
||||
private String img;
|
||||
@ApiModelProperty("徽章说明")
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageStatusEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum;
|
||||
import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum;
|
||||
import com.abin.mallchat.common.user.domain.entity.ItemConfig;
|
||||
import com.abin.mallchat.common.user.domain.entity.User;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp;
|
||||
@@ -35,11 +36,11 @@ public class MessageAdapter {
|
||||
|
||||
}
|
||||
|
||||
public static List<ChatMessageResp> buildMsgResp(List<Message> messages, Map<Long, Message> replyMap, Map<Long, User> userMap, List<MessageMark> msgMark, Long receiveUid) {
|
||||
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 -> {
|
||||
ChatMessageResp resp = new ChatMessageResp();
|
||||
resp.setFromUser(buildFromUser(userMap.get(a.getFromUid())));
|
||||
resp.setFromUser(buildFromUser(userMap.get(a.getFromUid()),itemMap));
|
||||
resp.setMessage(buildMessage(a, replyMap, userMap, markMap.getOrDefault(a.getId(), new ArrayList<>()), receiveUid));
|
||||
return resp;
|
||||
})
|
||||
@@ -80,11 +81,18 @@ public class MessageAdapter {
|
||||
return mark;
|
||||
}
|
||||
|
||||
private static ChatMessageResp.UserInfo buildFromUser(User fromUser) {
|
||||
private static ChatMessageResp.UserInfo buildFromUser(User fromUser, Map<Long, ItemConfig> itemMap) {
|
||||
ChatMessageResp.UserInfo userInfo = new ChatMessageResp.UserInfo();
|
||||
userInfo.setUsername(fromUser.getName());
|
||||
userInfo.setAvatar(fromUser.getAvatar());
|
||||
userInfo.setUid(fromUser.getId());
|
||||
if(Objects.nonNull(fromUser.getItemId())){
|
||||
ChatMessageResp.Badge badge =new ChatMessageResp.Badge();
|
||||
ItemConfig itemConfig = itemMap.get(fromUser.getItemId());
|
||||
badge.setImg(itemConfig.getImg());
|
||||
badge.setDescribe(itemConfig.getDescribe());
|
||||
userInfo.setBadge(badge);
|
||||
}
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@ import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||
import com.abin.mallchat.common.common.exception.BusinessException;
|
||||
import com.abin.mallchat.common.common.utils.AssertUtil;
|
||||
import com.abin.mallchat.common.user.dao.UserDao;
|
||||
import com.abin.mallchat.common.user.domain.entity.ItemConfig;
|
||||
import com.abin.mallchat.common.user.domain.entity.User;
|
||||
import com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum;
|
||||
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.ChatMessageMarkReq;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessagePageReq;
|
||||
@@ -69,6 +71,8 @@ public class ChatServiceImpl implements ChatService {
|
||||
private RoomDao roomDao;
|
||||
@Autowired
|
||||
private MessageMarkDao messageMarkDao;
|
||||
@Autowired
|
||||
private ItemCache itemCache;
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
@@ -209,7 +213,8 @@ public class ChatServiceImpl implements ChatService {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Map<Long, Message> replyMap = new HashMap<>();
|
||||
Map<Long, User> userMap = new HashMap<>();
|
||||
Map<Long, User> userMap;
|
||||
Map<Long, ItemConfig> itemMap;
|
||||
//批量查出回复的消息
|
||||
List<Long> replyIds = messages.stream().map(Message::getReplyMsgId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(replyIds)) {
|
||||
@@ -218,9 +223,11 @@ public class ChatServiceImpl implements ChatService {
|
||||
//批量查询消息关联用户
|
||||
Set<Long> uidSet = Stream.concat(replyMap.values().stream().map(Message::getFromUid), messages.stream().map(Message::getFromUid)).collect(Collectors.toSet());
|
||||
userMap = userCache.getUserInfoBatch(uidSet);
|
||||
//批量查询item信息
|
||||
itemMap = userMap.values().stream().map(User::getItemId).distinct().filter(Objects::nonNull).map(itemCache::getById).collect(Collectors.toMap(ItemConfig::getId,Function.identity()));
|
||||
//查询消息标志
|
||||
List<MessageMark> msgMark = messageMarkDao.getValidMarkByMsgIdBatch(messages.stream().map(Message::getId).collect(Collectors.toList()));
|
||||
return MessageAdapter.buildMsgResp(messages, replyMap, userMap, msgMark, receiveUid);
|
||||
return MessageAdapter.buildMsgResp(messages, replyMap, userMap, msgMark, receiveUid,itemMap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class UserOnlineListener {
|
||||
User user = event.getUser();
|
||||
userCache.online(user.getId(), user.getLastOptTime());
|
||||
//推送给所有在线用户,该用户登录成功
|
||||
webSocketService.sendToAllOnline(wsAdapter.buildOnlineNotifyResp(event.getUser()), event.getUser().getId());
|
||||
webSocketService.sendToAllOnline(wsAdapter.buildOnlineNotifyResp(event.getUser()), null);
|
||||
}
|
||||
|
||||
@Async
|
||||
|
||||
@@ -59,7 +59,7 @@ public class WxPortalController {
|
||||
log.error("callBack error",e);
|
||||
}
|
||||
RedirectView redirectView = new RedirectView();
|
||||
redirectView.setUrl("https://mp.weixin.qq.com/s/MKCWzoCIzvh5G_1sK5sLoA");
|
||||
redirectView.setUrl("https://mp.weixin.qq.com/s/m1SRsBG96kLJW5mPe4AVGA");
|
||||
return redirectView;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ public class BadgeResp {
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "徽章图标")
|
||||
private String image;
|
||||
private String img;
|
||||
|
||||
@ApiModelProperty(value = "徽章描述")
|
||||
private String describe;
|
||||
|
||||
@@ -91,7 +91,9 @@ public class WxMsgService {
|
||||
public void authorize(WxOAuth2UserInfo userInfo) {
|
||||
User user = userDao.getByOpenId(userInfo.getOpenid());
|
||||
//更新用户信息
|
||||
fillUserInfo(user.getId(), userInfo);
|
||||
if(Objects.isNull(user.getName())){
|
||||
fillUserInfo(user.getId(), userInfo);
|
||||
}
|
||||
//触发用户登录成功操作
|
||||
Integer eventKey = OPENID_EVENT_CODE_MAP.get(userInfo.getOpenid());
|
||||
login(user.getId(), eventKey);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.abin.mallchat.custom.user.service.handler;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.abin.mallchat.common.chat.dao.WxMsgDao;
|
||||
import com.abin.mallchat.common.chat.domain.entity.WxMsg;
|
||||
import com.abin.mallchat.custom.user.service.adapter.TextBuilder;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
@@ -9,6 +11,7 @@ import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -21,12 +24,18 @@ import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
|
||||
@Component
|
||||
public class MsgHandler extends AbstractHandler {
|
||||
|
||||
@Autowired
|
||||
private WxMsgDao wxMsgDao;
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
|
||||
Map<String, Object> context, WxMpService weixinService,
|
||||
WxSessionManager sessionManager) {
|
||||
if (true) {
|
||||
return WxMpXmlOutMessage.TEXT().build();
|
||||
WxMsg msg =new WxMsg();
|
||||
msg.setOpenId(wxMessage.getFromUser());
|
||||
msg.setMsg(wxMessage.getContent());
|
||||
wxMsgDao.save(msg);
|
||||
return null;
|
||||
}
|
||||
if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) {
|
||||
//可以选择将消息保存到本地
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.abin.mallchat.common.common.config.ThreadPoolConfig;
|
||||
import com.abin.mallchat.common.user.dao.UserDao;
|
||||
import com.abin.mallchat.common.user.domain.entity.User;
|
||||
import com.abin.mallchat.common.common.event.UserOfflineEvent;
|
||||
import com.abin.mallchat.common.user.service.cache.UserCache;
|
||||
import com.abin.mallchat.custom.user.domain.dto.ws.WSChannelExtraDTO;
|
||||
import com.abin.mallchat.custom.user.domain.vo.request.ws.WSAuthorize;
|
||||
import com.abin.mallchat.custom.user.domain.vo.response.ws.WSBaseResp;
|
||||
@@ -51,7 +52,8 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
* 所有已连接的websocket连接列表和一些额外参数
|
||||
*/
|
||||
private static final ConcurrentHashMap<Channel, WSChannelExtraDTO> ONLINE_WS_MAP = new ConcurrentHashMap<>();
|
||||
public static ConcurrentHashMap<Channel, WSChannelExtraDTO> getOnlineMap(){
|
||||
|
||||
public static ConcurrentHashMap<Channel, WSChannelExtraDTO> getOnlineMap() {
|
||||
return ONLINE_WS_MAP;
|
||||
}
|
||||
|
||||
@@ -67,6 +69,8 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
@Autowired
|
||||
@Qualifier(ThreadPoolConfig.WS_EXECUTOR)
|
||||
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
|
||||
@Autowired
|
||||
private UserCache userCache;
|
||||
|
||||
/**
|
||||
* 处理用户登录请求,需要返回一张带code的二维码
|
||||
@@ -144,12 +148,14 @@ public class WebSocketServiceImpl implements WebSocketService {
|
||||
//返回给用户登录成功
|
||||
sendMsg(channel, WSAdapter.buildLoginSuccessResp(user, token));
|
||||
//发送用户上线事件
|
||||
user.setLastOptTime(new Date());
|
||||
user.getIpInfo().refreshIp(NettyUtil.getAttr(channel, NettyUtil.IP));
|
||||
applicationEventPublisher.publishEvent(new UserOnlineEvent(this, user));
|
||||
boolean online = userCache.isOnline(user.getId());
|
||||
if (!online) {
|
||||
user.setLastOptTime(new Date());
|
||||
user.getIpInfo().refreshIp(NettyUtil.getAttr(channel, NettyUtil.IP));
|
||||
applicationEventPublisher.publishEvent(new UserOnlineEvent(this, user));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 用户上线
|
||||
*/
|
||||
|
||||
@@ -86,17 +86,18 @@ public class NettyWebSocketServerHandler extends SimpleChannelInboundHandler<Tex
|
||||
// 读取客户端发送的请求报文
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
|
||||
log.info("服务器端收到消息 = " + msg.text());
|
||||
WSBaseReq wsBaseReq = JSONUtil.toBean(msg.text(), WSBaseReq.class);
|
||||
WSReqTypeEnum wsReqTypeEnum = WSReqTypeEnum.of(wsBaseReq.getType());
|
||||
switch (wsReqTypeEnum) {
|
||||
case LOGIN:
|
||||
getService().handleLoginReq(ctx.channel());
|
||||
log.info("请求二维码 = " + msg.text());
|
||||
break;
|
||||
case HEARTBEAT:
|
||||
break;
|
||||
case AUTHORIZE:
|
||||
getService().authorize(ctx.channel(), JSONUtil.toBean(wsBaseReq.getData(), WSAuthorize.class));
|
||||
log.info("主动认证 = " + msg.text());
|
||||
default:
|
||||
log.info("未知类型");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user