From ee570cdbd5b21d47106501a552694bfabdb08f33 Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Sun, 29 Oct 2023 01:45:06 +0800 Subject: [PATCH] =?UTF-8?q?ui=E7=BE=8E=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/bx/imclient/IMClient.java | 19 +++- .../java/com/bx/imclient/sender/IMSender.java | 39 ++++--- .../implatform/controller/UserController.java | 14 ++- .../bx/implatform/service/IUserService.java | 6 + .../service/impl/GroupServiceImpl.java | 14 ++- .../impl/PrivateMessageServiceImpl.java | 1 - .../service/impl/UserServiceImpl.java | 48 +++++++- .../com/bx/implatform/vo/GroupMemberVO.java | 3 + .../bx/implatform/vo/OnlineTerminalVO.java | 24 ++++ .../bx/imserver/netty/IMChannelHandler.java | 4 +- .../netty/processor/HeartbeatProcessor.java | 4 +- im-ui/src/api/enums.js | 8 +- im-ui/src/assets/default_head.png | Bin 32272 -> 0 bytes im-ui/src/components/chat/ChatItem.vue | 2 +- im-ui/src/components/chat/ChatMessageItem.vue | 2 +- im-ui/src/components/common/HeadImage.vue | 67 +++++++++-- im-ui/src/components/common/UserInfo.vue | 22 ++-- im-ui/src/components/friend/AddFriend.vue | 5 +- im-ui/src/components/friend/FriendItem.vue | 19 ++-- im-ui/src/components/group/GroupItem.vue | 2 +- im-ui/src/components/group/GroupMember.vue | 4 +- im-ui/src/store/friendStore.js | 26 +++-- im-ui/src/view/Friend.vue | 4 +- im-ui/src/view/Group.vue | 11 +- im-ui/src/view/Home.vue | 10 +- im-ui/src/view/Login.vue | 2 +- im-uniapp/common/enums.js | 8 +- im-uniapp/components/chat-item/chat-item.vue | 11 +- .../chat-message-item/chat-message-item.vue | 65 ++++------- .../components/friend-item/friend-item.vue | 45 ++------ .../components/group-item/group-item.vue | 20 +--- .../components/head-image/head-image.vue | 104 ++++++++++++++++++ im-uniapp/pages/common/user-info.vue | 28 ++--- im-uniapp/pages/friend/friend-add.vue | 32 +++++- im-uniapp/pages/group/group-edit.vue | 4 +- im-uniapp/pages/group/group-info.vue | 30 +---- im-uniapp/pages/group/group-invite.vue | 37 ++++++- im-uniapp/pages/group/group-member.vue | 45 ++++++-- im-uniapp/store/friendStore.js | 36 ++++-- 39 files changed, 556 insertions(+), 269 deletions(-) create mode 100644 im-platform/src/main/java/com/bx/implatform/vo/OnlineTerminalVO.java delete mode 100644 im-ui/src/assets/default_head.png create mode 100644 im-uniapp/components/head-image/head-image.vue diff --git a/im-client/src/main/java/com/bx/imclient/IMClient.java b/im-client/src/main/java/com/bx/imclient/IMClient.java index a1e12ec..4b3e6e7 100644 --- a/im-client/src/main/java/com/bx/imclient/IMClient.java +++ b/im-client/src/main/java/com/bx/imclient/IMClient.java @@ -1,14 +1,14 @@ package com.bx.imclient; import com.bx.imclient.sender.IMSender; +import com.bx.imcommon.enums.IMTerminalType; import com.bx.imcommon.model.IMGroupMessage; import com.bx.imcommon.model.IMPrivateMessage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; -import java.util.Collection; -import java.util.Collections; import java.util.List; +import java.util.Map; @Configuration public class IMClient { @@ -31,8 +31,19 @@ public class IMClient { * @param userIds 用户id列表 * @return 在线的用户列表 */ - public List isOnline(List userIds){ - return imSender.isOnline(userIds); + public List getOnlineUser(List userIds){ + return imSender.getOnlineUser(userIds); + } + + + /** + * 判断多个用户是否在线 + * + * @param userIds 用户id列表 + * @return 在线的用户终端 + */ + public Map> getOnlineTerminal(List userIds){ + return imSender.getOnlineTerminal(userIds); } /** diff --git a/im-client/src/main/java/com/bx/imclient/sender/IMSender.java b/im-client/src/main/java/com/bx/imclient/sender/IMSender.java index c92a990..1d3dc87 100644 --- a/im-client/src/main/java/com/bx/imclient/sender/IMSender.java +++ b/im-client/src/main/java/com/bx/imclient/sender/IMSender.java @@ -14,6 +14,7 @@ import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @Service @@ -90,12 +91,12 @@ public class IMSender { List serverIds = redisTemplate.opsForValue().multiGet(sendMap.keySet()); // 格式:map<服务器id,list<接收方>> Map> serverMap = new HashMap<>(); - List offLineUsers = Collections.synchronizedList(new LinkedList<>()); + List offLineUsers = new LinkedList<>(); int idx = 0; for (Map.Entry entry : sendMap.entrySet()) { Integer serverId = (Integer)serverIds.get(idx++); if (serverId != null) { - List list = serverMap.computeIfAbsent(serverId, o -> Collections.synchronizedList(new LinkedList<>())); + List list = serverMap.computeIfAbsent(serverId, o -> new LinkedList<>()); list.add(entry.getValue()); } else { // 加入离线列表 @@ -150,34 +151,40 @@ public class IMSender { } } - public Boolean isOnline(Long userId) { - String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, userId.toString(), "*"); - return !redisTemplate.keys(key).isEmpty(); - } - - public List isOnline(List userIds){ + public Map> getOnlineTerminal(List userIds){ if(CollectionUtil.isEmpty(userIds)){ - return Collections.emptyList(); + return Collections.EMPTY_MAP; } // 把所有用户的key都存起来 - Map keyMap = new HashMap<>(); + Map userMap = new HashMap<>(); for(Long id:userIds){ for (Integer terminal : IMTerminalType.codes()) { String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, id.toString(), terminal.toString()); - keyMap.put(key,id); + userMap.put(key,new IMUserInfo(id,terminal)); } } // 批量拉取 - List serverIds = redisTemplate.opsForValue().multiGet(keyMap.keySet()); + List serverIds = redisTemplate.opsForValue().multiGet(userMap.keySet()); int idx = 0; - List onlineIds = new LinkedList<>(); - for (Map.Entry entry : keyMap.entrySet()) { + Map> onlineMap = new HashMap<>(); + for (Map.Entry entry : userMap.entrySet()) { // serverid有值表示用户在线 if(serverIds.get(idx++) != null){ - onlineIds.add(entry.getValue()); + IMUserInfo userInfo = entry.getValue(); + List terminals = onlineMap.computeIfAbsent(userInfo.getId(), o -> new LinkedList<>()); + terminals.add(IMTerminalType.fromCode(userInfo.getTerminal())); } } // 去重并返回 - return onlineIds.stream().distinct().collect(Collectors.toList()); + return onlineMap; + } + + public Boolean isOnline(Long userId) { + String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, userId.toString(), "*"); + return !redisTemplate.keys(key).isEmpty(); + } + + public List getOnlineUser(List userIds){ + return new LinkedList<>(getOnlineTerminal(userIds).keySet()); } } diff --git a/im-platform/src/main/java/com/bx/implatform/controller/UserController.java b/im-platform/src/main/java/com/bx/implatform/controller/UserController.java index 63efcd8..22222c0 100644 --- a/im-platform/src/main/java/com/bx/implatform/controller/UserController.java +++ b/im-platform/src/main/java/com/bx/implatform/controller/UserController.java @@ -7,6 +7,7 @@ import com.bx.implatform.service.IUserService; import com.bx.implatform.session.SessionContext; import com.bx.implatform.session.UserSession; import com.bx.implatform.util.BeanUtils; +import com.bx.implatform.vo.OnlineTerminalVO; import com.bx.implatform.vo.UserVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -34,6 +35,13 @@ public class UserController { return ResultUtils.success(onlineIds); } + @GetMapping("/terminal/online") + @ApiOperation(value = "判断用户哪个终端在线",notes="返回在线的用户id的终端集合") + public Result> getOnlineTerminal(@NotEmpty @RequestParam("userIds") String userIds){ + return ResultUtils.success(userService.getOnlineTerminals(userIds)); + } + + @GetMapping("/self") @ApiOperation(value = "获取当前用户信息",notes="获取当前用户信息") public Result findSelfInfo(){ @@ -46,10 +54,8 @@ public class UserController { @GetMapping("/find/{id}") @ApiOperation(value = "查找用户",notes="根据id查找用户") - public Result findByIde(@NotEmpty @PathVariable("id") long id){ - User user = userService.getById(id); - UserVO userVO = BeanUtils.copyProperties(user,UserVO.class); - return ResultUtils.success(userVO); + public Result findById(@NotEmpty @PathVariable("id") Long id){ + return ResultUtils.success(userService.findUserById(id)); } @PutMapping("/update") diff --git a/im-platform/src/main/java/com/bx/implatform/service/IUserService.java b/im-platform/src/main/java/com/bx/implatform/service/IUserService.java index 107d51e..c675567 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/IUserService.java +++ b/im-platform/src/main/java/com/bx/implatform/service/IUserService.java @@ -6,6 +6,7 @@ import com.bx.implatform.entity.User; import com.bx.implatform.dto.LoginDTO; import com.bx.implatform.dto.RegisterDTO; import com.bx.implatform.vo.LoginVO; +import com.bx.implatform.vo.OnlineTerminalVO; import com.bx.implatform.vo.UserVO; import java.util.List; @@ -25,8 +26,13 @@ public interface IUserService extends IService { void update(UserVO vo); + UserVO findUserById(Long id); + List findUserByName(String name); List checkOnline(String userIds); + List getOnlineTerminals(String userIds); + + } diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java index e2104fc..623d64f 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java +++ b/im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java @@ -3,6 +3,7 @@ package com.bx.implatform.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bx.imclient.IMClient; import com.bx.implatform.contant.Constant; import com.bx.implatform.contant.RedisKey; import com.bx.implatform.entity.Friend; @@ -52,6 +53,9 @@ public class GroupServiceImpl extends ServiceImpl implements @Autowired private IFriendService friendsService; + @Autowired + private IMClient imClient; + /** * 创建新群聊 * @@ -292,7 +296,15 @@ public class GroupServiceImpl extends ServiceImpl implements @Override public List findGroupMembers(Long groupId) { List members = groupMemberService.findByGroupId(groupId); - return members.stream().map(m->BeanUtils.copyProperties(m,GroupMemberVO.class)).collect(Collectors.toList()); + List userIds = members.stream().map(GroupMember::getUserId).collect(Collectors.toList()); + List onlineUserIds = imClient.getOnlineUser(userIds); + return members.stream().map(m->{ + GroupMemberVO vo = BeanUtils.copyProperties(m,GroupMemberVO.class); + vo.setOnline(onlineUserIds.contains(m.getUserId())); + return vo; + }).sorted((m1,m2)->{ + return m2.getOnline().compareTo(m1.getOnline()); + }).collect(Collectors.toList()); } } diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java index 269a937..09fadef 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java +++ b/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java @@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.bx.imclient.IMClient; import com.bx.imcommon.contant.IMConstant; -import com.bx.imcommon.enums.IMTerminalType; import com.bx.imcommon.model.IMPrivateMessage; import com.bx.imcommon.model.IMUserInfo; import com.bx.implatform.entity.Friend; diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java index 0d43247..0d9a8bf 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java +++ b/im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.bx.imclient.IMClient; +import com.bx.imcommon.enums.IMTerminalType; import com.bx.imcommon.util.JwtUtil; import com.bx.implatform.config.JwtProperties; import com.bx.implatform.dto.LoginDTO; @@ -24,6 +25,7 @@ import com.bx.implatform.session.SessionContext; import com.bx.implatform.session.UserSession; import com.bx.implatform.util.BeanUtils; import com.bx.implatform.vo.LoginVO; +import com.bx.implatform.vo.OnlineTerminalVO; import com.bx.implatform.vo.UserVO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -33,7 +35,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Arrays; +import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; @@ -95,7 +99,7 @@ public class UserServiceImpl extends ServiceImpl implements IU /** * 用refreshToken换取新 token * - * @param refreshToken + * @param refreshToken 刷新token * @return 登录token */ @Override @@ -150,7 +154,7 @@ public class UserServiceImpl extends ServiceImpl implements IU * 根据用户名查询用户 * * @param username 用户名 - * @return + * @return 用户信息 */ @Override public User findUserByUserName(String username) { @@ -205,12 +209,25 @@ public class UserServiceImpl extends ServiceImpl implements IU log.info("用户信息更新,用户:{}}", user); } + /** + * 根据用户昵id查询用户以及在线状态 + * + * @param id 用户id + * @return 用户信息 + */ + @Override + public UserVO findUserById(Long id) { + User user = this.getById(id); + UserVO vo = BeanUtils.copyProperties(user,UserVO.class); + vo.setOnline(imClient.isOnline(id)); + return vo; + } /** * 根据用户昵称查询用户,最多返回20条数据 * * @param name 用户名或昵称 - * @return + * @return 用户列表 */ @Override public List findUserByName(String name) { @@ -221,7 +238,7 @@ public class UserServiceImpl extends ServiceImpl implements IU .last("limit 20"); List users = this.list(queryWrapper); List userIds = users.stream().map(User::getId).collect(Collectors.toList()); - List onlineUserIds = imClient.isOnline(userIds); + List onlineUserIds = imClient.getOnlineUser(userIds); return users.stream().map(u-> { UserVO vo = BeanUtils.copyProperties(u,UserVO.class); vo.setOnline(onlineUserIds.contains(u.getId())); @@ -239,7 +256,28 @@ public class UserServiceImpl extends ServiceImpl implements IU public List checkOnline(String userIds) { List userIdList = Arrays.stream(userIds.split(",")) .map(Long::parseLong).collect(Collectors.toList()); - return imClient.isOnline(userIdList); + return imClient.getOnlineUser(userIdList); } + + /** + * 获取用户在线的终端类型 + * + * @param userIds 用户id,多个用‘,’分割 + * @return 在线用户终端 + */ + @Override + public List getOnlineTerminals(String userIds) { + List userIdList = Arrays.stream(userIds.split(",")) + .map(Long::parseLong).collect(Collectors.toList()); + // 查询在线的终端 + Map> terminalMap = imClient.getOnlineTerminal(userIdList); + // 组装vo + List vos = new LinkedList<>(); + terminalMap.forEach((userId,types)->{ + List terminals = types.stream().map(IMTerminalType::code).collect(Collectors.toList()); + vos.add(new OnlineTerminalVO(userId,terminals)); + }); + return vos; + } } diff --git a/im-platform/src/main/java/com/bx/implatform/vo/GroupMemberVO.java b/im-platform/src/main/java/com/bx/implatform/vo/GroupMemberVO.java index 7428985..2e605c9 100644 --- a/im-platform/src/main/java/com/bx/implatform/vo/GroupMemberVO.java +++ b/im-platform/src/main/java/com/bx/implatform/vo/GroupMemberVO.java @@ -21,6 +21,9 @@ public class GroupMemberVO { @ApiModelProperty("是否已退出") private Boolean quit; + @ApiModelProperty(value = "是否在线") + private Boolean online; + @ApiModelProperty("备注") private String remark; diff --git a/im-platform/src/main/java/com/bx/implatform/vo/OnlineTerminalVO.java b/im-platform/src/main/java/com/bx/implatform/vo/OnlineTerminalVO.java new file mode 100644 index 0000000..4aed6c1 --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/vo/OnlineTerminalVO.java @@ -0,0 +1,24 @@ +package com.bx.implatform.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.List; + +/** + * @author: 谢绍许 + * @date: 2023-10-28 21:17:59 + * @version: 1.0 + */ +@Data +@AllArgsConstructor +public class OnlineTerminalVO { + + @ApiModelProperty(value = "用户id") + private Long userId; + + @ApiModelProperty(value = "在线终端类型") + private List terminals; + +} diff --git a/im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java b/im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java index babd2a0..d748d6e 100644 --- a/im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java +++ b/im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java @@ -91,8 +91,8 @@ public class IMChannelHandler extends SimpleChannelInboundHandler { AttributeKey attr = AttributeKey.valueOf("USER_ID"); Long userId = ctx.channel().attr(attr).get(); AttributeKey terminalAttr = AttributeKey.valueOf(ChannelAttrKey.TERMINAL_TYPE); - Integer ternimal = ctx.channel().attr(terminalAttr).get(); - log.info("心跳超时,即将断开连接,用户id:{},终端类型:{} ",userId,ternimal); + Integer terminal = ctx.channel().attr(terminalAttr).get(); + log.info("心跳超时,即将断开连接,用户id:{},终端类型:{} ",userId,terminal); ctx.channel().close(); } } else { diff --git a/im-server/src/main/java/com/bx/imserver/netty/processor/HeartbeatProcessor.java b/im-server/src/main/java/com/bx/imserver/netty/processor/HeartbeatProcessor.java index b72bccd..f24f848 100644 --- a/im-server/src/main/java/com/bx/imserver/netty/processor/HeartbeatProcessor.java +++ b/im-server/src/main/java/com/bx/imserver/netty/processor/HeartbeatProcessor.java @@ -45,8 +45,8 @@ public class HeartbeatProcessor extends AbstractMessageProcessor userIdAttr = AttributeKey.valueOf(ChannelAttrKey.USER_ID); Long userId = ctx.channel().attr(userIdAttr).get(); AttributeKey terminalAttr = AttributeKey.valueOf(ChannelAttrKey.TERMINAL_TYPE); - Integer ternimal = ctx.channel().attr(terminalAttr).get(); - String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID,userId.toString(),ternimal.toString()); + Integer terminal = ctx.channel().attr(terminalAttr).get(); + String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID,userId.toString(),terminal.toString()); redisTemplate.expire(key, IMConstant.ONLINE_TIMEOUT_SECOND, TimeUnit.SECONDS); } } diff --git a/im-ui/src/api/enums.js b/im-ui/src/api/enums.js index 0d1e0fb..27bfb78 100644 --- a/im-ui/src/api/enums.js +++ b/im-ui/src/api/enums.js @@ -22,7 +22,13 @@ const USER_STATE = { BUSY: 2 } +const TERMINAL_TYPE = { + WEB: 0, + APP: 1 +} + export { MESSAGE_TYPE, - USER_STATE + USER_STATE, + TERMINAL_TYPE } diff --git a/im-ui/src/assets/default_head.png b/im-ui/src/assets/default_head.png deleted file mode 100644 index c7a9e0ef251e8b3f0154a2e7ef8b273133edf31c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32272 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
- +
{{chat.unreadCount}}
diff --git a/im-ui/src/components/chat/ChatMessageItem.vue b/im-ui/src/components/chat/ChatMessageItem.vue index a0824a3..0f7b3bf 100644 --- a/im-ui/src/components/chat/ChatMessageItem.vue +++ b/im-ui/src/components/chat/ChatMessageItem.vue @@ -5,7 +5,7 @@
- +
diff --git a/im-ui/src/components/common/HeadImage.vue b/im-ui/src/components/common/HeadImage.vue index edece98..9c34808 100644 --- a/im-ui/src/components/common/HeadImage.vue +++ b/im-ui/src/components/common/HeadImage.vue @@ -1,6 +1,9 @@ @@ -10,7 +13,11 @@ export default { name: "headImage", data() { - return {} + return { + colors:["#7dd24b","#c7515a","#db68ef","#15d29b","#85029b", + "#c9b455","#fb2609","#bda818","#af0831","#326eb6"] + + } }, props: { id:{ @@ -22,6 +29,14 @@ }, url: { type: String + }, + name:{ + type: String, + default: "X" + }, + online:{ + type: Boolean, + default:false } }, methods:{ @@ -36,26 +51,54 @@ }) } } - } + }, + computed:{ + avatarImageStyle(){ + return `width:${this.size}px; height:${this.size}px;` + }, + avatarTextStyle(){ + return `width: ${this.size}px;height:${this.size}px; + color:${this.textColor};font-size:${this.size*0.6}px;` + }, + textColor(){ + let hash = 0; + for (var i = 0; i< this.name.length; i++) { + hash += this.name.charCodeAt(i); + } + return this.colors[hash%this.colors.length]; + } + } } diff --git a/im-ui/src/components/common/UserInfo.vue b/im-ui/src/components/common/UserInfo.vue index 70bd364..98be670 100644 --- a/im-ui/src/components/common/UserInfo.vue +++ b/im-ui/src/components/common/UserInfo.vue @@ -3,7 +3,8 @@