Procházet zdrojové kódy

fix : websocket交互, 消息处理代码提交

bilingfeng před 1 rokem
rodič
revize
bf49c27562
17 změnil soubory, kde provedl 336 přidání a 323 odebrání
  1. 6 1
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/enums/KfWebSocketMsgEnum.java
  2. 10 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/dto/KfWebSocketMsgDTO.java
  3. 8 3
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/params/KfWebSocketMsgParam.java
  4. 0 57
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/vo/KfMsgRoomVO.java
  5. 0 58
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/vo/KfMsgWaitUserVO.java
  6. 0 25
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/vo/KfWebsocketGameVO.java
  7. 3 3
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/rpc/impl/KfMsgRpcImpl.java
  8. 17 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IKfAppletMsgService.java
  9. 0 7
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IKfRoomMsgService.java
  10. 9 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IKfRoomService.java
  11. 153 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfAppletMsgServiceImpl.java
  12. 7 124
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfRoomMsgServiceImpl.java
  13. 33 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfRoomServiceImpl.java
  14. 0 14
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfSessionUserServiceImpl.java
  15. 2 0
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/websocket/KfMsgRedisListener.java
  16. 78 31
      game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/websocket/KfMsgWebsocketHandler.java
  17. 10 0
      game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/KfSessionUser.java

+ 6 - 1
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/enums/KfWebSocketMsgEnum.java

@@ -13,7 +13,12 @@ import lombok.Getter;
 public enum KfWebSocketMsgEnum {
 
     /**
-     * 首次建立连接, 接收前端消息, 返回游戏列表, 待接入列表, 已接入房间列表
+     * 握手, 接收前端消息, 返回游戏列表
+     */
+    WEBSOCKET_MSG_KF_HAND_SHAKE("WEBSOCKET_MSG_KF_HAND_SHAKE"),
+
+    /**
+     * 建立连接, 接收前端消息, 待接入列表, 已接入房间列表
      */
     WEBSOCKET_MSG_KF_CREATE_CONNECT("WEBSOCKET_MSG_KF_CREATE_CONNECT"),
 

+ 10 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/dto/KfWebSocketMsgDTO.java

@@ -38,6 +38,16 @@ public class KfWebSocketMsgDTO {
      */
     private PageBean page;
 
+    /**
+     * 游戏id
+     */
+    private Long gameId;
+
+    /**
+     * 房间id
+     */
+    private Long roomId;
+
     /**
      * 结果信息
      */

+ 8 - 3
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/params/KfWebSocketMsgParam.java

@@ -12,17 +12,22 @@ import lombok.Data;
 public class KfWebSocketMsgParam {
 
     /**
-     * webSocket消息类型
+     * webSocket消息类型, 必传参数
      */
     private KfWebSocketMsgEnum webSocketMsgType;
 
     /**
-     * 客服登录token, 消息类型为首次连接(WEBSOCKET_MSG_CONNECT)时, 必须携带, 否则无法建立连接
+     * 客服登录token, 必传参数
      */
     private String token;
 
     /**
-     * 分页信息, 分页获取数据的时候, 必须携带
+     * 游戏id, 必传参数(首次握手除外)
+     */
+    private Long gameId;
+
+    /**
+     * 分页信息, 分页获取数据的时候, 必须传
      */
     private PageBean page;
 

+ 0 - 57
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/vo/KfMsgRoomVO.java

@@ -1,57 +0,0 @@
-package com.zanxiang.game.module.manage.pojo.vo;
-
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-/**
- * @author : lingfeng
- * @time : 2024-02-26
- * @description : 客服消息房间
- */
-@Data
-public class KfMsgRoomVO {
-
-    /**
-     * 主键
-     */
-    @ApiModelProperty(notes = "主键")
-    private Long id;
-
-    /**
-     * 玩家open_id
-     */
-    @ApiModelProperty(notes = "玩家open_id")
-    private String openId;
-
-    /**
-     * 游戏id
-     */
-    @ApiModelProperty(notes = "游戏id")
-    private String gameId;
-
-    /**
-     * 客服id
-     */
-    @ApiModelProperty(notes = "客服id")
-    private Long kfUserId;
-
-    /**
-     * 房间在线状态
-     */
-    @ApiModelProperty(notes = "房间在线状态")
-    private Boolean online;
-
-    /**
-     * 最后一条消息
-     */
-    @ApiModelProperty(notes = "最后一条消息")
-    private String lastMsg;
-
-    /**
-     * 最后一条消息时间
-     */
-    @ApiModelProperty(notes = "最后一条消息时间")
-    private LocalDateTime lastMsgTime;
-}

+ 0 - 58
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/vo/KfMsgWaitUserVO.java

@@ -1,58 +0,0 @@
-package com.zanxiang.game.module.manage.pojo.vo;
-
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-/**
- * @author : lingfeng
- * @time : 2024-02-26
- * @description : 待接入玩家
- */
-@Data
-public class KfMsgWaitUserVO {
-
-    /**
-     * 玩家openId
-     */
-    @ApiModelProperty(notes = "玩家openId")
-    private String openId;
-
-    /**
-     * 游戏id
-     */
-    @ApiModelProperty(notes = "游戏id")
-    private Long gameId;
-
-    /**
-     * 最近角色id
-     */
-    @ApiModelProperty(notes = "最近角色id")
-    private String lastRoleId;
-
-    /**
-     * 最近角色名称
-     */
-    @ApiModelProperty(notes = "最近角色名称")
-    private String lastRoleName;
-
-    /**
-     * 最后一条消息
-     */
-    @ApiModelProperty(notes = "最后一条消息")
-    private String lastMsg;
-
-    /**
-     * 最后一条消息时间
-     */
-    @ApiModelProperty(notes = "最后一条消息时间")
-    private LocalDateTime lastMsgTime;
-
-    /**
-     * 开始等待时间
-     */
-    @ApiModelProperty(notes = "开始等待时间")
-    private LocalDateTime waitStartTime;
-
-}

+ 0 - 25
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/vo/KfWebsocketGameVO.java

@@ -1,25 +0,0 @@
-package com.zanxiang.game.module.manage.pojo.vo;
-
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-/**
- * @author : lingfeng
- * @time : 2024-02-26
- * @description : 客服游戏
- */
-@Data
-public class KfWebsocketGameVO {
-
-    /**
-     * 应用id
-     */
-    @ApiModelProperty(notes = "应用id")
-    private String appId;
-
-    /**
-     * 应用名称
-     */
-    @ApiModelProperty(notes = "应用名称")
-    private String appName;
-}

+ 3 - 3
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/rpc/impl/KfMsgRpcImpl.java

@@ -1,7 +1,7 @@
 package com.zanxiang.game.module.manage.rpc.impl;
 
 import com.zanxiang.game.module.base.rpc.IKfMsgRpc;
-import com.zanxiang.game.module.manage.service.IKfRoomMsgService;
+import com.zanxiang.game.module.manage.service.IKfAppletMsgService;
 import org.apache.dubbo.config.annotation.DubboService;
 import org.springframework.beans.factory.annotation.Autowired;
 
@@ -14,10 +14,10 @@ import org.springframework.beans.factory.annotation.Autowired;
 public class KfMsgRpcImpl implements IKfMsgRpc {
 
     @Autowired
-    private IKfRoomMsgService kfRoomMsgService;
+    private IKfAppletMsgService kfAppletMsgService;
 
     @Override
     public void appletMsg(String postData) {
-        kfRoomMsgService.appletMsg(postData);
+        kfAppletMsgService.appletMsg(postData);
     }
 }

+ 17 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IKfAppletMsgService.java

@@ -0,0 +1,17 @@
+package com.zanxiang.game.module.manage.service;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-02-28
+ * @description : 小程序客服消息处理
+ */
+public interface IKfAppletMsgService {
+
+    /**
+     * 接收到SDK转发的小程序消息
+     *
+     * @param postData : 消息内容
+     */
+    void appletMsg(String postData);
+
+}

+ 0 - 7
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IKfRoomMsgService.java

@@ -9,11 +9,4 @@ import com.zanxiang.game.module.mybatis.entity.KfRoomMsg;
  * @description : 客服房间消息
  */
 public interface IKfRoomMsgService extends IService<KfRoomMsg> {
-
-    /**
-     * 接收到SDK转发的小程序消息
-     *
-     * @param postData : 消息内容
-     */
-    void appletMsg(String postData);
 }

+ 9 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/IKfRoomService.java

@@ -13,6 +13,15 @@ import java.util.List;
  */
 public interface IKfRoomService extends IService<KfRoom> {
 
+    /**
+     * 玩家加入房间
+     *
+     * @param openId : 玩家openId
+     * @param gameId : 游戏id
+     * @return : 返回更新结果
+     */
+    boolean userJoinRoom(String openId, Long gameId);
+
     /**
      * 客服获取游戏列表
      *

+ 153 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfAppletMsgServiceImpl.java

@@ -0,0 +1,153 @@
+package com.zanxiang.game.module.manage.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.zanxiang.game.module.manage.enums.KfRoomMsgOwnerEnum;
+import com.zanxiang.game.module.manage.enums.KfRoomMsgTypeEnum;
+import com.zanxiang.game.module.manage.enums.KfWebSocketMsgEnum;
+import com.zanxiang.game.module.manage.pojo.dto.KfAppletMsgDTO;
+import com.zanxiang.game.module.manage.pojo.dto.KfWebSocketMsgDTO;
+import com.zanxiang.game.module.manage.service.*;
+import com.zanxiang.game.module.manage.websocket.KfMsgWebsocketHandler;
+import com.zanxiang.game.module.mybatis.entity.*;
+import com.zanxiang.module.util.JsonUtil;
+import com.zanxiang.module.util.bean.BeanUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.Collections;
+import java.util.Objects;
+
+/**
+ * @author : lingfeng
+ * @time : 2024-02-28
+ * @description : 小程序客服消息处理
+ */
+@Slf4j
+@Service
+public class KfAppletMsgServiceImpl implements IKfAppletMsgService {
+
+    @Autowired
+    private IKfSessionUserService kfSessionUserService;
+
+    @Autowired
+    private KfMsgWebsocketHandler kfMsgWebsocketHandler;
+
+    @Autowired
+    private IKfRoomService kfRoomService;
+
+    @Autowired
+    private IGameAppletService gameAppletService;
+
+    @Autowired
+    private IUserService userService;
+
+    @Autowired
+    private IGameUserRoleService gameUserRoleService;
+
+    @Autowired
+    private IKfRoomMsgService kfRoomMsgService;
+
+    @Override
+    public void appletMsg(String postData) {
+        log.error("接收到SDK转发的小程序消息, postData : {}", postData);
+        KfAppletMsgDTO kfAppletMsgDTO = JsonUtil.toObj(postData, KfAppletMsgDTO.class);
+        GameApplet gameApplet = gameAppletService.getOne(new LambdaQueryWrapper<GameApplet>()
+                .eq(GameApplet::getGhId, kfAppletMsgDTO.getToUserName()));
+        //用户进入会话事件
+        if (Objects.equals(kfAppletMsgDTO.getMsgType(), KfAppletMsgDTO.MSG_TYPE_EVENT)
+                && Objects.equals(kfAppletMsgDTO.getEvent(), KfAppletMsgDTO.EVENT_USER_ENTER_TEMP_SESSION)) {
+            KfSessionUser kfSessionUser = kfSessionUserService.getById(kfAppletMsgDTO.getFromUserName());
+            if (kfSessionUser != null) {
+                return;
+            }
+            //创建保存用户信息
+            kfSessionUserService.save(this.transform(kfAppletMsgDTO, gameApplet));
+            return;
+        }
+        //非玩家消息, 不做处理
+        if (kfAppletMsgDTO.getMsgId() == null) {
+            return;
+        }
+        //查询玩家的房间连接状态
+        KfRoom kfRoom = kfRoomService.getOne(new LambdaQueryWrapper<KfRoom>()
+                .eq(KfRoom::getOpenId, kfAppletMsgDTO.getFromUserName())
+                .eq(KfRoom::getOnline, Boolean.TRUE));
+        //消息存储
+        KfWebSocketMsgDTO.MsgContentBean msgContent = this.getMsgContent(kfAppletMsgDTO);
+        KfRoomMsg kfRoomMsg = this.transform(kfAppletMsgDTO, gameApplet, kfRoom, postData, msgContent);
+        kfRoomMsgService.save(kfRoomMsg);
+        //玩家状态更新为待接入状态
+        if (kfRoom == null) {
+            kfSessionUserService.update(new LambdaUpdateWrapper<KfSessionUser>()
+                    .set(KfSessionUser::getIsWait, Boolean.TRUE)
+                    .set(KfSessionUser::getWaitStartTime, LocalDateTime.now())
+                    .set(KfSessionUser::getUpdateTime, LocalDateTime.now())
+                    .eq(KfSessionUser::getOpenId, kfAppletMsgDTO.getFromUserName()));
+        }
+        //消息转发到redis频道
+        kfMsgWebsocketHandler.pushMessage(this.transform(kfRoomMsg, msgContent));
+    }
+
+    private KfWebSocketMsgDTO transform(KfRoomMsg kfRoomMsg, KfWebSocketMsgDTO.MsgContentBean msgContent) {
+        //todo : 需要修改
+        KfWebSocketMsgDTO.RoomMsgBean roomMsgBean = BeanUtil.copy(kfRoomMsg, KfWebSocketMsgDTO.RoomMsgBean.class);
+        roomMsgBean.setContent(msgContent);
+        KfWebSocketMsgEnum kfWebSocketMsgEnum = roomMsgBean.getRoomId() == null ?
+                KfWebSocketMsgEnum.WEBSOCKET_MSG_WAIT_LIST : KfWebSocketMsgEnum.WEBSOCKET_MSG_ROOM_MSG;
+        return KfWebSocketMsgDTO.builder()
+                .webSocketMsgType(kfWebSocketMsgEnum)
+                .roomMsgList(Collections.singletonList(roomMsgBean))
+                .build();
+    }
+
+    private KfSessionUser transform(KfAppletMsgDTO kfAppletMsgDTO, GameApplet gameApplet) {
+        //查询用户
+        User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getOpenId, kfAppletMsgDTO.getFromUserName()));
+        //最近角色信息
+        GameUserRole gameUserRole = null;
+        if (user != null) {
+            gameUserRole = gameUserRoleService.getLastGameUserRoleName(user.getId(), user.getGameId());
+        }
+        return KfSessionUser.builder()
+                .openId(kfAppletMsgDTO.getFromUserName())
+                .gameId(gameApplet.getGameId())
+                .userId(user == null ? null : user.getId())
+                .isWait(Boolean.FALSE)
+                .lastRoleId(gameUserRole == null ? null : gameUserRole.getRoleId())
+                .lastRoleName(gameUserRole == null ? null : gameUserRole.getRoleName())
+                .createTime(LocalDateTime.now())
+                .updateTime(LocalDateTime.now())
+                .build();
+    }
+
+    private KfRoomMsg transform(KfAppletMsgDTO kfAppletMsgDTO, GameApplet gameApplet, KfRoom kfRoom, String postData,
+                                KfWebSocketMsgDTO.MsgContentBean msgContent) {
+        return KfRoomMsg.builder()
+                .msgId(String.valueOf(kfAppletMsgDTO.getMsgId()))
+                .msgType(kfAppletMsgDTO.getMsgType())
+                .gameId(gameApplet.getGameId())
+                .openId(kfAppletMsgDTO.getFromUserName())
+                .readStatus(Boolean.FALSE)
+                .roomId(kfRoom == null ? null : kfRoom.getId())
+                .msgOwner(KfRoomMsgOwnerEnum.KF_MSG_OWNER_USER.getValue())
+                .content(JsonUtil.toString(msgContent))
+                .source(postData)
+                .createTime(LocalDateTime.now())
+                .build();
+    }
+
+    private KfWebSocketMsgDTO.MsgContentBean getMsgContent(KfAppletMsgDTO kfAppletMsgDTO) {
+        //todo : 这里要考虑图片是否要传到oss上, 用自己的网络地址, 腾讯的图片地址不能保证一直有效
+        KfWebSocketMsgDTO.MsgContentBean msgContentBean = new KfWebSocketMsgDTO.MsgContentBean();
+        if (Objects.equals(KfRoomMsgTypeEnum.KF_MSG_TYPE_TEXT.getValue(), kfAppletMsgDTO.getMsgType())) {
+            msgContentBean.setText(kfAppletMsgDTO.getContent());
+        }
+        if (Objects.equals(KfRoomMsgTypeEnum.KF_MSG_TYPE_IMAGE.getValue(), kfAppletMsgDTO.getMsgType())) {
+            msgContentBean.setImage(kfAppletMsgDTO.getPicUrl());
+        }
+        return msgContentBean;
+    }
+}

+ 7 - 124
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfRoomMsgServiceImpl.java

@@ -1,26 +1,14 @@
 package com.zanxiang.game.module.manage.service.impl;
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.zanxiang.game.module.manage.enums.KfRoomMsgOwnerEnum;
-import com.zanxiang.game.module.manage.enums.KfRoomMsgTypeEnum;
-import com.zanxiang.game.module.manage.enums.KfWebSocketMsgEnum;
-import com.zanxiang.game.module.manage.pojo.dto.KfAppletMsgDTO;
 import com.zanxiang.game.module.manage.pojo.dto.KfWebSocketMsgDTO;
-import com.zanxiang.game.module.manage.service.*;
-import com.zanxiang.game.module.manage.websocket.KfMsgWebsocketHandler;
-import com.zanxiang.game.module.mybatis.entity.*;
+import com.zanxiang.game.module.manage.pojo.params.KfWebSocketMsgParam;
+import com.zanxiang.game.module.manage.service.IKfRoomMsgService;
+import com.zanxiang.game.module.mybatis.entity.KfRoomMsg;
 import com.zanxiang.game.module.mybatis.mapper.KfRoomMsgMapper;
-import com.zanxiang.module.util.JsonUtil;
-import com.zanxiang.module.util.bean.BeanUtil;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-
-import java.time.LocalDateTime;
-import java.util.Collections;
-import java.util.Objects;
+import reactor.util.function.Tuple2;
 
 /**
  * @author : lingfeng
@@ -31,112 +19,7 @@ import java.util.Objects;
 @Service
 public class KfRoomMsgServiceImpl extends ServiceImpl<KfRoomMsgMapper, KfRoomMsg> implements IKfRoomMsgService {
 
-    @Autowired
-    private IKfSessionUserService kfSessionUserService;
-
-    @Autowired
-    private KfMsgWebsocketHandler kfMsgWebsocketHandler;
-
-    @Autowired
-    private IKfRoomService kfRoomService;
-
-    @Autowired
-    private IGameAppletService gameAppletService;
-
-    @Autowired
-    private IUserService userService;
-
-    @Override
-    public void appletMsg(String postData) {
-        log.error("接收到SDK转发的小程序消息, postData : {}", postData);
-        KfAppletMsgDTO kfAppletMsgDTO = JsonUtil.toObj(postData, KfAppletMsgDTO.class);
-        GameApplet gameApplet = gameAppletService.getOne(new LambdaQueryWrapper<GameApplet>()
-                .eq(GameApplet::getGhId, kfAppletMsgDTO.getToUserName()));
-        //用户进入会话事件
-        if (Objects.equals(kfAppletMsgDTO.getMsgType(), KfAppletMsgDTO.MSG_TYPE_EVENT)
-                && Objects.equals(kfAppletMsgDTO.getEvent(), KfAppletMsgDTO.EVENT_USER_ENTER_TEMP_SESSION)) {
-            KfSessionUser kfSessionUser = kfSessionUserService.getById(kfAppletMsgDTO.getFromUserName());
-            if (kfSessionUser != null) {
-                return;
-            }
-            User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getOpenId, kfAppletMsgDTO.getFromUserName()));
-            //创建保存用户信息
-            kfSessionUserService.save(this.transform(kfAppletMsgDTO, gameApplet, user));
-            return;
-        }
-        //非玩家消息, 不做处理
-        if (kfAppletMsgDTO.getMsgId() == null) {
-            return;
-        }
-        //查询玩家的房间连接状态
-        KfRoom kfRoom = kfRoomService.getOne(new LambdaQueryWrapper<KfRoom>()
-                .eq(KfRoom::getOpenId, kfAppletMsgDTO.getFromUserName())
-                .eq(KfRoom::getOnline, Boolean.TRUE));
-        //消息存储
-        KfWebSocketMsgDTO.MsgContentBean msgContent = this.getMsgContent(kfAppletMsgDTO);
-        KfRoomMsg kfRoomMsg = this.transform(kfAppletMsgDTO, gameApplet, kfRoom, postData, msgContent);
-        super.save(kfRoomMsg);
-        //玩家状态更新为待接入状态
-        if (kfRoom == null) {
-            kfSessionUserService.update(new LambdaUpdateWrapper<KfSessionUser>()
-                    .set(KfSessionUser::getIsWait, Boolean.TRUE)
-                    .set(KfSessionUser::getWaitStartTime, LocalDateTime.now())
-                    .set(KfSessionUser::getUpdateTime, LocalDateTime.now())
-                    .eq(KfSessionUser::getOpenId, kfAppletMsgDTO.getFromUserName()));
-        }
-        //消息转发到redis频道
-        kfMsgWebsocketHandler.pushMessage(this.transform(kfRoomMsg, msgContent));
-    }
-
-    private KfWebSocketMsgDTO transform(KfRoomMsg kfRoomMsg, KfWebSocketMsgDTO.MsgContentBean msgContent) {
-        //todo : 需要修改
-        KfWebSocketMsgDTO.RoomMsgBean roomMsgBean = BeanUtil.copy(kfRoomMsg, KfWebSocketMsgDTO.RoomMsgBean.class);
-        roomMsgBean.setContent(msgContent);
-        KfWebSocketMsgEnum kfWebSocketMsgEnum = roomMsgBean.getRoomId() == null ?
-                KfWebSocketMsgEnum.WEBSOCKET_MSG_WAIT_LIST : KfWebSocketMsgEnum.WEBSOCKET_MSG_ROOM_MSG;
-        return KfWebSocketMsgDTO.builder()
-                .webSocketMsgType(kfWebSocketMsgEnum)
-                .roomMsgList(Collections.singletonList(roomMsgBean))
-                .build();
-    }
-
-    private KfSessionUser transform(KfAppletMsgDTO kfAppletMsgDTO, GameApplet gameApplet, User user) {
-        return KfSessionUser.builder()
-                .openId(kfAppletMsgDTO.getFromUserName())
-                .gameId(gameApplet.getGameId())
-                .userId(user == null ? null : user.getId())
-                .isWait(Boolean.FALSE)
-                .createTime(LocalDateTime.now())
-                .updateTime(LocalDateTime.now())
-                .build();
-    }
-
-    private KfRoomMsg transform(KfAppletMsgDTO kfAppletMsgDTO, GameApplet gameApplet, KfRoom kfRoom, String postData,
-                                KfWebSocketMsgDTO.MsgContentBean msgContent) {
-        return KfRoomMsg.builder()
-                .msgId(String.valueOf(kfAppletMsgDTO.getMsgId()))
-                .msgType(kfAppletMsgDTO.getMsgType())
-                .gameId(gameApplet.getGameId())
-                .openId(kfAppletMsgDTO.getFromUserName())
-                .readStatus(Boolean.FALSE)
-                .roomId(kfRoom == null ? null : kfRoom.getId())
-                .msgOwner(KfRoomMsgOwnerEnum.KF_MSG_OWNER_USER.getValue())
-                .content(JsonUtil.toString(msgContent))
-                .source(postData)
-                .createTime(LocalDateTime.now())
-                .build();
-    }
-
-    private KfWebSocketMsgDTO.MsgContentBean getMsgContent(KfAppletMsgDTO kfAppletMsgDTO) {
-        //todo : 这里要考虑图片是否要传到oss上, 用自己的网络地址, 腾讯的图片地址不能保证一直有效
-        KfWebSocketMsgDTO.MsgContentBean msgContentBean = new KfWebSocketMsgDTO.MsgContentBean();
-        if (Objects.equals(KfRoomMsgTypeEnum.KF_MSG_TYPE_TEXT.getValue(), kfAppletMsgDTO.getMsgType())) {
-            msgContentBean.setText(kfAppletMsgDTO.getContent());
-        }
-        if (Objects.equals(KfRoomMsgTypeEnum.KF_MSG_TYPE_IMAGE.getValue(), kfAppletMsgDTO.getMsgType())) {
-            msgContentBean.setImage(kfAppletMsgDTO.getPicUrl());
-        }
-        return msgContentBean;
-    }
-
+//    public Tuple2<> msgRoomHistory(Long roomId, KfWebSocketMsgParam.PageBean page) {
+//
+//    }
 }

+ 33 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfRoomServiceImpl.java

@@ -1,6 +1,7 @@
 package com.zanxiang.game.module.manage.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zanxiang.erp.security.util.SecurityUtil;
@@ -15,6 +16,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.time.LocalDateTime;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -42,6 +44,37 @@ public class KfRoomServiceImpl extends ServiceImpl<KfRoomMapper, KfRoom> impleme
     @Autowired
     private IKfRoomMsgService kfRoomMsgService;
 
+    @Autowired
+    private IUserService userService;
+
+    @Override
+    public boolean userJoinRoom(String openId, Long gameId) {
+        KfRoom kfRoom = super.getOne(new LambdaQueryWrapper<KfRoom>()
+                .eq(KfRoom::getOpenId, openId)
+                .eq(KfRoom::getKfUserId, SecurityUtil.getUserId()));
+        if (kfRoom == null) {
+            return super.save(this.transform(openId, gameId));
+        }
+        return super.update(new LambdaUpdateWrapper<KfRoom>()
+                .set(KfRoom::getOnline, Boolean.TRUE)
+                .set(KfRoom::getUpdateTime, LocalDateTime.now()));
+    }
+
+    private KfRoom transform(String openId, Long gameId) {
+        User user = userService.getOne(new LambdaQueryWrapper<User>()
+                .eq(User::getGameId, gameId)
+                .eq(User::getOpenId, openId));
+        return KfRoom.builder()
+                .gameId(gameId)
+                .openId(openId)
+                .userId(user == null ? null : user.getId())
+                .kfUserId(SecurityUtil.getUserId())
+                .online(Boolean.TRUE)
+                .createTime(LocalDateTime.now())
+                .updateTime(LocalDateTime.now())
+                .build();
+    }
+
     @Override
     public List<KfWebSocketMsgDTO.GameBean> getKfGameList() {
         List<GameAuth> gameAuthList = gameAuthService.list(new LambdaQueryWrapper<GameAuth>()

+ 0 - 14
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfSessionUserServiceImpl.java

@@ -4,10 +4,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zanxiang.game.module.manage.enums.KfRoomMsgTypeEnum;
 import com.zanxiang.game.module.manage.pojo.dto.KfWebSocketMsgDTO;
-import com.zanxiang.game.module.manage.service.IGameUserRoleService;
 import com.zanxiang.game.module.manage.service.IKfRoomMsgService;
 import com.zanxiang.game.module.manage.service.IKfSessionUserService;
-import com.zanxiang.game.module.mybatis.entity.GameUserRole;
 import com.zanxiang.game.module.mybatis.entity.KfRoomMsg;
 import com.zanxiang.game.module.mybatis.entity.KfSessionUser;
 import com.zanxiang.game.module.mybatis.mapper.KfSessionUserMapper;
@@ -31,9 +29,6 @@ import java.util.stream.Collectors;
 @Service
 public class KfSessionUserServiceImpl extends ServiceImpl<KfSessionUserMapper, KfSessionUser> implements IKfSessionUserService {
 
-    @Autowired
-    private IGameUserRoleService gameUserRoleService;
-
     @Autowired
     private IKfRoomMsgService kfRoomMsgService;
 
@@ -49,15 +44,6 @@ public class KfSessionUserServiceImpl extends ServiceImpl<KfSessionUserMapper, K
             return null;
         }
         KfWebSocketMsgDTO.WaitUserBean waitUserBean = BeanUtil.copy(kfSessionUser, KfWebSocketMsgDTO.WaitUserBean.class);
-        //最近角色信息
-        GameUserRole gameUserRole = null;
-        if (kfSessionUser.getUserId() != null) {
-            gameUserRole = gameUserRoleService.getLastGameUserRoleName(kfSessionUser.getUserId(), kfSessionUser.getGameId());
-        }
-        if (gameUserRole != null) {
-            waitUserBean.setLastRoleId(gameUserRole.getRoleId());
-            waitUserBean.setLastRoleName(gameUserRole.getRoleName());
-        }
         //最后一条消息
         KfRoomMsg kfRoomMsg = kfRoomMsgService.getOne(new LambdaQueryWrapper<KfRoomMsg>()
                 .eq(KfRoomMsg::getOpenId, kfSessionUser.getOpenId())

+ 2 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/websocket/KfMsgRedisListener.java

@@ -35,6 +35,7 @@ public class KfMsgRedisListener implements MessageListener {
         Long kfUserId = kfWebSocketMsgDTO.getKfUserId();
         //发送给指定客服
         if (kfUserId != null) {
+            log.error("发送消息给指定客服 kfUserId : {}, kfWebSocketMsgDTO : {}", kfUserId, JsonUtil.toString(kfWebSocketMsgDTO));
             WebSocketSession session = kfMsgWebSocketSessionRegistry.getSession(kfUserId);
             if (session != null && session.isOpen()) {
                 try {
@@ -45,6 +46,7 @@ public class KfMsgRedisListener implements MessageListener {
             return;
         }
         //发送给所有在线客服
+        log.error("发送消息给所有客服客服 kfWebSocketMsgDTO : {}", JsonUtil.toString(kfWebSocketMsgDTO));
         List<WebSocketSession> openSessions = kfMsgWebSocketSessionRegistry.getAllAessions();
         openSessions.forEach(session -> {
             if (session != null && session.isOpen()) {

+ 78 - 31
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/websocket/KfMsgWebsocketHandler.java

@@ -10,6 +10,7 @@ import com.zanxiang.game.module.manage.pojo.params.KfWebSocketMsgParam;
 import com.zanxiang.game.module.manage.service.IKfRoomService;
 import com.zanxiang.game.module.manage.service.IKfSessionUserService;
 import com.zanxiang.game.module.mybatis.entity.KfRoom;
+import com.zanxiang.game.module.mybatis.entity.KfSessionUser;
 import com.zanxiang.module.util.JsonUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.logging.log4j.util.Strings;
@@ -64,6 +65,7 @@ public class KfMsgWebsocketHandler implements WebSocketHandler {
         log.error("收到前端消息 msgStr : {}", msgStr);
         //消息解析
         KfWebSocketMsgParam kfWebSocketMsgParam = JsonUtil.toObj(msgStr, KfWebSocketMsgParam.class);
+        log.error("收到前端消息解析结果 kfWebSocketMsgParam : {}", JsonUtil.toString(kfWebSocketMsgParam));
         //消息类型
         KfWebSocketMsgEnum webSocketMsgType = kfWebSocketMsgParam.getWebSocketMsgType();
         //请求令牌
@@ -72,29 +74,27 @@ public class KfMsgWebsocketHandler implements WebSocketHandler {
         boolean tokenCheckResult = this.tokenCheck(webSocketMsgType, token);
         //身份验证失败, 没有后续动作
         if (!tokenCheckResult) {
+            log.error("token验证失败, token : {}", token);
             return;
         }
-        //将token设置到当前线程
-        SecurityUtil.fillToken(token);
-        //添加会话
-        Long kfUserId = SecurityUtil.getUserId();
-        session.getAttributes().put("kfUserId", kfUserId);
-        kfMsgWebSocketSessionRegistry.addSession(kfUserId, session);
-        //客服创建连接-消息处理
+        //握手-消息处理
+        if (Objects.equals(kfWebSocketMsgParam.getWebSocketMsgType(), KfWebSocketMsgEnum.WEBSOCKET_MSG_KF_HAND_SHAKE)) {
+            log.error("首次握手, kfUserId : {}", SecurityUtil.getUserId());
+            this.kfHandShake(session, webSocketMsgType);
+        }
+        //创建连接-消息处理
         if (Objects.equals(kfWebSocketMsgParam.getWebSocketMsgType(), KfWebSocketMsgEnum.WEBSOCKET_MSG_KF_CREATE_CONNECT)) {
-            this.kfConnect(kfWebSocketMsgParam);
+            log.error("创建连接, kfUserId : {}", SecurityUtil.getUserId());
+            this.kfCreateConnect(webSocketMsgType);
         }
         //玩家接入-消息处理
         if (Objects.equals(kfWebSocketMsgParam.getWebSocketMsgType(), KfWebSocketMsgEnum.WEBSOCKET_MSG_USER_CONNECT_JOIN)) {
-
+            log.error("玩家接入, kfUserId : {}", SecurityUtil.getUserId());
+            this.userConnectJoin(kfWebSocketMsgParam);
         }
         //获取房间历史消息-消息处理
         if (Objects.equals(kfWebSocketMsgParam.getWebSocketMsgType(), KfWebSocketMsgEnum.WEBSOCKET_MSG_ROOM_HISTORY)) {
-
-        }
-        //客服发送消息-消息处理
-        if (Objects.equals(kfWebSocketMsgParam.getWebSocketMsgType(), KfWebSocketMsgEnum.WEBSOCKET_MSG_KF_SEND)) {
-
+            log.error("获取房间历史消息, kfUserId : {}", SecurityUtil.getUserId());
         }
         //客服发送消息-消息处理
         if (Objects.equals(kfWebSocketMsgParam.getWebSocketMsgType(), KfWebSocketMsgEnum.WEBSOCKET_MSG_KF_SEND)) {
@@ -144,39 +144,86 @@ public class KfMsgWebsocketHandler implements WebSocketHandler {
         return false;
     }
 
-    private boolean tokenCheck(KfWebSocketMsgEnum webSocketMsgType, String token) {
-        //令牌为空
-        if (Strings.isBlank(token)) {
-            this.pushMessage(KfWebSocketMsgDTO.fail(webSocketMsgType, "非法参数, token令牌不可为空"));
-            return Boolean.FALSE;
+    private void msgRoomHistory(KfWebSocketMsgParam param) {
+        if (param.getRoomId() == null || param.getPage() == null) {
+            this.pushMessage(KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(),
+                    "获取房间历史消息参数错误, roomId和page都不可为空, param : " + JsonUtil.toString(param)));
         }
-        //令牌验证
-        TokenInfo tokenInfo = SecurityUtil.parseToken(token);
-        if (tokenInfo == null) {
-            this.pushMessage(KfWebSocketMsgDTO.fail(webSocketMsgType, "参数错误, 令牌验证不通过"));
-            return Boolean.FALSE;
+    }
+
+    private void userConnectJoin(KfWebSocketMsgParam param) {
+        if (Strings.isBlank(param.getOpenId()) || param.getGameId() == null) {
+            this.pushMessage(KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(),
+                    "接入玩家参数错误, openId和gameId都不可为空, param : " + JsonUtil.toString(param)));
         }
-        //返回验证通过
-        return Boolean.TRUE;
+        //玩家更新
+        kfSessionUserService.update(new LambdaUpdateWrapper<KfSessionUser>()
+                .set(KfSessionUser::getIsWait, Boolean.FALSE)
+                .set(KfSessionUser::getUpdateTime, LocalDateTime.now()));
+        //房间更新
+        kfRoomService.userJoinRoom(param.getOpenId(), param.getGameId());
+        //发送消息, 给该客服返回完整的已接入房间列表
+        List<KfWebSocketMsgDTO.RoomBean> roomList = kfRoomService.getOnlineRoomList();
+        this.pushMessage(KfWebSocketMsgDTO.builder()
+                .webSocketMsgType(param.getWebSocketMsgType())
+                .kfUserId(SecurityUtil.getUserId())
+                .roomList(roomList)
+                .build());
+        //发送消息, 给所有在线客服推送完整待接入列表
+        List<KfWebSocketMsgDTO.WaitUserBean> waitUserList = kfSessionUserService.getWaitUserList();
+        this.pushMessage(KfWebSocketMsgDTO.builder()
+                .webSocketMsgType(param.getWebSocketMsgType())
+                .waitUserList(waitUserList)
+                .build());
     }
 
-    private void kfConnect(KfWebSocketMsgParam kfWebSocketMsgParam) {
-        //获取游戏列表
-        List<KfWebSocketMsgDTO.GameBean> gameList = kfRoomService.getKfGameList();
+    private void kfCreateConnect(KfWebSocketMsgEnum msgTypeEnum) {
         //获取待接入列表
         List<KfWebSocketMsgDTO.WaitUserBean> waitUserList = kfSessionUserService.getWaitUserList();
         //获取已接入房间列表
         List<KfWebSocketMsgDTO.RoomBean> roomList = kfRoomService.getOnlineRoomList();
         //发送消息
         this.pushMessage(KfWebSocketMsgDTO.builder()
-                .webSocketMsgType(kfWebSocketMsgParam.getWebSocketMsgType())
+                .webSocketMsgType(msgTypeEnum)
                 .kfUserId(SecurityUtil.getUserId())
-                .gameList(gameList)
                 .waitUserList(waitUserList)
                 .roomList(roomList)
                 .build());
     }
 
+    private void kfHandShake(WebSocketSession session, KfWebSocketMsgEnum msgTypeEnum) {
+        //添加会话
+        Long kfUserId = SecurityUtil.getUserId();
+        session.getAttributes().put("kfUserId", kfUserId);
+        kfMsgWebSocketSessionRegistry.addSession(kfUserId, session);
+        //获取游戏列表
+        List<KfWebSocketMsgDTO.GameBean> gameList = kfRoomService.getKfGameList();
+        //发送消息
+        this.pushMessage(KfWebSocketMsgDTO.builder()
+                .webSocketMsgType(msgTypeEnum)
+                .kfUserId(SecurityUtil.getUserId())
+                .gameList(gameList)
+                .build());
+    }
+
+    private boolean tokenCheck(KfWebSocketMsgEnum webSocketMsgType, String token) {
+        //令牌为空
+        if (Strings.isBlank(token)) {
+            this.pushMessage(KfWebSocketMsgDTO.fail(webSocketMsgType, "非法参数, token令牌不可为空"));
+            return Boolean.FALSE;
+        }
+        //令牌验证
+        TokenInfo tokenInfo = SecurityUtil.parseToken(token);
+        if (tokenInfo == null) {
+            this.pushMessage(KfWebSocketMsgDTO.fail(webSocketMsgType, "参数错误, 令牌验证不通过"));
+            return Boolean.FALSE;
+        }
+        //将token设置到当前线程
+        SecurityUtil.fillToken(token);
+        //返回验证通过
+        return Boolean.TRUE;
+    }
+
     /**
      * 消息发送到redis广播
      */

+ 10 - 0
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/KfSessionUser.java

@@ -48,6 +48,16 @@ public class KfSessionUser {
      */
     private LocalDateTime waitStartTime;
 
+    /**
+     * 最近角色id
+     */
+    private String lastRoleId;
+
+    /**
+     * 最近角色名称
+     */
+    private String lastRoleName;
+
     /**
      * 创建时间
      */