u
This commit is contained in:
1 parent
a6dbe24dd4
commit
52b16ed2b0
21 files changed
+442
-105
No files matched your search
@@ -89,4 +89,18 @@ public class ImController {
|
|||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/friend/{friendId}")
|
||||||
|
public Result<FriendProfileVO> getFriendProfile(@PathVariable("friendId") Long friendId){
|
||||||
|
FriendProfileVO friendProfileVO = imFriendService.getFriendProfile(friendId);
|
||||||
|
|
||||||
|
return Result.success(friendProfileVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/group/{groupId}")
|
||||||
|
public Result<GroupProfileVO> getGroupProfile(@PathVariable("groupId") Long groupId){
|
||||||
|
GroupProfileVO groupProfileVO = imGroupService.getGroupProfile(groupId);
|
||||||
|
|
||||||
|
return Result.success(groupProfileVO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,8 +13,7 @@ public enum MessageTypeEnums {
|
|||||||
OFFLINE(6),
|
OFFLINE(6),
|
||||||
GROUP_OFFLINE(7),
|
GROUP_OFFLINE(7),
|
||||||
PRIVATE(8),
|
PRIVATE(8),
|
||||||
GROUP(9),
|
GROUP(9);
|
||||||
FRIEND_UPDATE(10);
|
|
||||||
|
|
||||||
private final int code;
|
private final int code;
|
||||||
|
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ import cn.link56.im.message.MessageResponse;
|
|||||||
import cn.link56.im.model.dto.GroupDTO;
|
import cn.link56.im.model.dto.GroupDTO;
|
||||||
import cn.link56.im.model.dto.LoginDTO;
|
import cn.link56.im.model.dto.LoginDTO;
|
||||||
import cn.link56.im.model.dto.PrivateDTO;
|
import cn.link56.im.model.dto.PrivateDTO;
|
||||||
|
import cn.link56.im.model.po.ImGroupMessage;
|
||||||
import cn.link56.im.model.po.ImPrivateMessage;
|
import cn.link56.im.model.po.ImPrivateMessage;
|
||||||
|
import cn.link56.im.model.vo.GroupMessageVO;
|
||||||
import cn.link56.im.model.vo.PrivateMessageVO;
|
import cn.link56.im.model.vo.PrivateMessageVO;
|
||||||
import cn.link56.im.model.vo.QueryFriendVO;
|
import cn.link56.im.model.vo.QueryFriendVO;
|
||||||
import cn.link56.im.service.ImFriendService;
|
import cn.link56.im.service.*;
|
||||||
import cn.link56.im.service.ImGroupUserService;
|
|
||||||
import cn.link56.im.service.ImPrivateMessageService;
|
|
||||||
import cn.link56.im.storage.SessionManager;
|
import cn.link56.im.storage.SessionManager;
|
||||||
import cn.link56.im.utils.MessageDataConverter;
|
import cn.link56.im.utils.MessageDataConverter;
|
||||||
import cn.link56.im.utils.MessageWriter;
|
import cn.link56.im.utils.MessageWriter;
|
||||||
@@ -40,6 +40,10 @@ public class MessageHandler {
|
|||||||
private ImPrivateMessageService imPrivateMessageService;
|
private ImPrivateMessageService imPrivateMessageService;
|
||||||
@Resource
|
@Resource
|
||||||
private CompanyUserService companyUserService;
|
private CompanyUserService companyUserService;
|
||||||
|
@Resource
|
||||||
|
private ImGroupMessageService imGroupMessageService;
|
||||||
|
@Resource
|
||||||
|
private ImGroupService imGroupService;
|
||||||
|
|
||||||
// 处理消息
|
// 处理消息
|
||||||
public void handleMessage(Channel channel, MessageRequest request) {
|
public void handleMessage(Channel channel, MessageRequest request) {
|
||||||
@@ -104,7 +108,7 @@ public class MessageHandler {
|
|||||||
MessageWriter.broadcastToUsers(onlineFriends,MessageResponse.success(MessageTypeEnums.ONLINE).setFrom(from));
|
MessageWriter.broadcastToUsers(onlineFriends,MessageResponse.success(MessageTypeEnums.ONLINE).setFrom(from));
|
||||||
|
|
||||||
// 通知群组
|
// 通知群组
|
||||||
List<Long> onlineGroupUsers = imGroupUserService.getOnlineGroupUsers(from);
|
List<Long> onlineGroupUsers = imGroupUserService.getAllOnlineGroupUsers(from);
|
||||||
MessageWriter.broadcastToUsers(onlineGroupUsers,MessageResponse.success(MessageTypeEnums.GROUP_ONLINE).setFrom(from));
|
MessageWriter.broadcastToUsers(onlineGroupUsers,MessageResponse.success(MessageTypeEnums.GROUP_ONLINE).setFrom(from));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +119,7 @@ public class MessageHandler {
|
|||||||
MessageWriter.broadcastToUsers(onlineFriends,MessageResponse.success(MessageTypeEnums.OFFLINE).setFrom(from));
|
MessageWriter.broadcastToUsers(onlineFriends,MessageResponse.success(MessageTypeEnums.OFFLINE).setFrom(from));
|
||||||
|
|
||||||
// 通知群组
|
// 通知群组
|
||||||
List<Long> onlineGroupUsers = imGroupUserService.getOnlineGroupUsers(from);
|
List<Long> onlineGroupUsers = imGroupUserService.getAllOnlineGroupUsers(from);
|
||||||
MessageWriter.broadcastToUsers(onlineGroupUsers,MessageResponse.success(MessageTypeEnums.GROUP_OFFLINE).setFrom(from));
|
MessageWriter.broadcastToUsers(onlineGroupUsers,MessageResponse.success(MessageTypeEnums.GROUP_OFFLINE).setFrom(from));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,22 +136,6 @@ public class MessageHandler {
|
|||||||
// 好友关系建立
|
// 好友关系建立
|
||||||
imFriendService.createFriend(to,from);
|
imFriendService.createFriend(to,from);
|
||||||
|
|
||||||
// 通知建立了好友关系
|
|
||||||
if (SessionManager.isOnline(to)) {
|
|
||||||
CompanyUser companyUser = companyUserService.getById(from);
|
|
||||||
if (ObjectUtils.isNotEmpty(companyUser)){
|
|
||||||
QueryFriendVO queryFriendVO = new QueryFriendVO();
|
|
||||||
queryFriendVO.setFriendId(from);
|
|
||||||
queryFriendVO.setFriendName(companyUser.getName());
|
|
||||||
queryFriendVO.setFriendAvatar(companyUser.getAvatar());
|
|
||||||
queryFriendVO.setIsOnline(true);
|
|
||||||
|
|
||||||
queryFriendVO.setUnreadCount(0);
|
|
||||||
|
|
||||||
MessageWriter.writeToUser(to,MessageResponse.success(MessageTypeEnums.FRIEND_UPDATE,from).setData(queryFriendVO));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存
|
// 保存
|
||||||
Long privateMessageID = IdGenerator.nextId();
|
Long privateMessageID = IdGenerator.nextId();
|
||||||
Long sendTime = TimeUtils.getCurrentTimestampMillis();
|
Long sendTime = TimeUtils.getCurrentTimestampMillis();
|
||||||
@@ -188,11 +176,51 @@ public class MessageHandler {
|
|||||||
// 群聊逻辑
|
// 群聊逻辑
|
||||||
private void handleGroup(Channel channel, MessageRequest request) {
|
private void handleGroup(Channel channel, MessageRequest request) {
|
||||||
Long from = request.getFrom();
|
Long from = request.getFrom();
|
||||||
Long to = request.getTo();
|
Long groupId = request.getTo();
|
||||||
|
|
||||||
GroupDTO dto = MessageDataConverter.convert(request.getData(), GroupDTO.class);
|
GroupDTO dto = MessageDataConverter.convert(request.getData(), GroupDTO.class);
|
||||||
String content = dto.getContent();
|
String content = dto.getContent();
|
||||||
Integer type = dto.getType();
|
Integer type = dto.getType();
|
||||||
String tempId = dto.getTempId();
|
String tempId = dto.getTempId();
|
||||||
|
String senderName = dto.getSenderName();
|
||||||
|
String senderAvatar = dto.getSenderAvatar();
|
||||||
|
|
||||||
|
// 将消息插入到数据库中
|
||||||
|
long nextId = IdGenerator.nextId();
|
||||||
|
long timestampMillis = TimeUtils.getCurrentTimestampMillis();
|
||||||
|
|
||||||
|
ImGroupMessage imGroupMessage = new ImGroupMessage();
|
||||||
|
imGroupMessage.setId(nextId);
|
||||||
|
imGroupMessage.setContent(content);
|
||||||
|
imGroupMessage.setType(type);
|
||||||
|
imGroupMessage.setSenderId(from);
|
||||||
|
imGroupMessage.setSendTime(timestampMillis);
|
||||||
|
imGroupMessage.setGroupId(groupId);
|
||||||
|
|
||||||
|
imGroupMessageService.save(imGroupMessage);
|
||||||
|
|
||||||
|
// 更新未读状态
|
||||||
|
imGroupUserService.updateGroupUnreadCount(groupId,from);
|
||||||
|
// 更新lastMessageId
|
||||||
|
imGroupService.updateLaseMessageId(groupId,nextId);
|
||||||
|
|
||||||
|
// 构建回复消息
|
||||||
|
GroupMessageVO groupMessageVO = new GroupMessageVO();
|
||||||
|
groupMessageVO.setTempId(tempId);
|
||||||
|
groupMessageVO.setId(nextId);
|
||||||
|
groupMessageVO.setSenderId(from);
|
||||||
|
groupMessageVO.setContent(content);
|
||||||
|
groupMessageVO.setType(type);
|
||||||
|
groupMessageVO.setSendTime(timestampMillis);
|
||||||
|
groupMessageVO.setGroupId(groupId);
|
||||||
|
groupMessageVO.setSenderName(senderName);
|
||||||
|
groupMessageVO.setSenderAvatar(senderAvatar);
|
||||||
|
|
||||||
|
// 通知建立群组关系
|
||||||
|
|
||||||
|
|
||||||
|
// 查询该群在线的用户
|
||||||
|
List<Long> onlineGroupUsers = imGroupUserService.getGroupOnlineUserIds(groupId);
|
||||||
|
MessageWriter.broadcastToUsers(onlineGroupUsers,MessageResponse.success(MessageTypeEnums.GROUP,groupId).setData(groupMessageVO));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package cn.link56.im.mapper;
|
package cn.link56.im.mapper;
|
||||||
|
|
||||||
import cn.link56.im.model.po.ImFriend;
|
import cn.link56.im.model.po.ImFriend;
|
||||||
|
import cn.link56.im.model.vo.FriendProfileVO;
|
||||||
import cn.link56.im.model.vo.QueryFriendVO;
|
import cn.link56.im.model.vo.QueryFriendVO;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
@@ -34,4 +35,10 @@ public interface ImFriendMapper extends BaseMapper<ImFriend> {
|
|||||||
@Param("userId") Long userId,
|
@Param("userId") Long userId,
|
||||||
@Param("friendId") Long friendId
|
@Param("friendId") Long friendId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
FriendProfileVO selectFriendProfile(
|
||||||
|
@Param("userId") Long userId,
|
||||||
|
@Param("friendId") Long friendId
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package cn.link56.im.mapper;
|
package cn.link56.im.mapper;
|
||||||
|
|
||||||
import cn.link56.im.model.po.ImGroup;
|
import cn.link56.im.model.po.ImGroup;
|
||||||
import cn.link56.im.model.vo.QueryFriendVO;
|
import cn.link56.im.model.vo.GroupProfileVO;
|
||||||
import cn.link56.im.model.vo.QueryGroupVO;
|
import cn.link56.im.model.vo.QueryGroupVO;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
@@ -21,4 +21,8 @@ public interface ImGroupMapper extends BaseMapper<ImGroup> {
|
|||||||
|
|
||||||
Long selectGroupTotal(@Param("userId") Long userId,
|
Long selectGroupTotal(@Param("userId") Long userId,
|
||||||
@Param("name") String name);
|
@Param("name") String name);
|
||||||
|
|
||||||
|
GroupProfileVO selectGroupProfile(
|
||||||
|
@Param("groupId") Long groupId,
|
||||||
|
@Param("userId") Long userId);
|
||||||
}
|
}
|
||||||
@@ -11,4 +11,7 @@ public class GroupDTO {
|
|||||||
private String content;
|
private String content;
|
||||||
private Integer type;
|
private Integer type;
|
||||||
private String tempId;
|
private String tempId;
|
||||||
|
|
||||||
|
private String senderAvatar;
|
||||||
|
private String senderName;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package cn.link56.im.model.vo;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class FriendProfileVO {
|
||||||
|
private Long friendId;
|
||||||
|
private String friendName;
|
||||||
|
private String friendAvatar;
|
||||||
|
private Integer unreadCount;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package cn.link56.im.model.vo;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class GroupMessageVO extends QueryGroupMessageVO {
|
||||||
|
private String tempId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package cn.link56.im.model.vo;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class GroupProfileVO {
|
||||||
|
private Long groupId;
|
||||||
|
private String groupName;
|
||||||
|
private String groupAvatar;
|
||||||
|
|
||||||
|
private Integer unreadCount;
|
||||||
|
}
|
||||||
@@ -16,7 +16,6 @@ public class QueryFriendVO {
|
|||||||
|
|
||||||
private Integer unreadCount;
|
private Integer unreadCount;
|
||||||
|
|
||||||
private Long lastMessageId;
|
|
||||||
private Long lastMessageTime;
|
private Long lastMessageTime;
|
||||||
private Integer lastMessageType;
|
private Integer lastMessageType;
|
||||||
private String lastMessageContent;
|
private String lastMessageContent;
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ public class QueryGroupVO {
|
|||||||
|
|
||||||
private Integer unreadCount;
|
private Integer unreadCount;
|
||||||
|
|
||||||
private Long lastMessageId;
|
|
||||||
private Long lastMessageTime;
|
private Long lastMessageTime;
|
||||||
private Integer lastMessageType;
|
private Integer lastMessageType;
|
||||||
private String lastMessageContent;
|
private String lastMessageContent;
|
||||||
|
|
||||||
|
private String lastMessageSenderName;
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import cn.link56.common.utils.snowflake.idgen.IdGenerator;
|
|||||||
import cn.link56.im.mapper.ImFriendMapper;
|
import cn.link56.im.mapper.ImFriendMapper;
|
||||||
import cn.link56.im.model.dto.QueryFriendDTO;
|
import cn.link56.im.model.dto.QueryFriendDTO;
|
||||||
import cn.link56.im.model.po.ImFriend;
|
import cn.link56.im.model.po.ImFriend;
|
||||||
|
import cn.link56.im.model.vo.FriendProfileVO;
|
||||||
import cn.link56.im.model.vo.QueryFriendVO;
|
import cn.link56.im.model.vo.QueryFriendVO;
|
||||||
import cn.link56.im.storage.SessionManager;
|
import cn.link56.im.storage.SessionManager;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
@@ -103,4 +104,10 @@ public class ImFriendService extends ServiceImpl<ImFriendMapper, ImFriend> {
|
|||||||
public void decreaseUnreadCount(Long userId,Long friendId){
|
public void decreaseUnreadCount(Long userId,Long friendId){
|
||||||
imFriendMapper.decreaseUnreadCount(userId, friendId);
|
imFriendMapper.decreaseUnreadCount(userId, friendId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FriendProfileVO getFriendProfile(Long friendId) {
|
||||||
|
Long userId = UserContext.getUserId();
|
||||||
|
|
||||||
|
return imFriendMapper.selectFriendProfile(userId, friendId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,13 +5,17 @@ import cn.link56.common.context.UserContext;
|
|||||||
import cn.link56.im.mapper.ImGroupMapper;
|
import cn.link56.im.mapper.ImGroupMapper;
|
||||||
import cn.link56.im.model.dto.QueryGroupDTO;
|
import cn.link56.im.model.dto.QueryGroupDTO;
|
||||||
import cn.link56.im.model.po.ImGroup;
|
import cn.link56.im.model.po.ImGroup;
|
||||||
|
import cn.link56.im.model.vo.GroupProfileVO;
|
||||||
import cn.link56.im.model.vo.QueryFriendVO;
|
import cn.link56.im.model.vo.QueryFriendVO;
|
||||||
import cn.link56.im.model.vo.QueryGroupVO;
|
import cn.link56.im.model.vo.QueryGroupVO;
|
||||||
|
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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class ImGroupService extends ServiceImpl<ImGroupMapper, ImGroup>{
|
public class ImGroupService extends ServiceImpl<ImGroupMapper, ImGroup>{
|
||||||
@@ -32,4 +36,18 @@ public class ImGroupService extends ServiceImpl<ImGroupMapper, ImGroup>{
|
|||||||
|
|
||||||
return new BasePageVO<>(total,queryFriendVOS);
|
return new BasePageVO<>(total,queryFriendVOS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void updateLaseMessageId(Long groupId,Long lastMessageId){
|
||||||
|
LambdaUpdateWrapper<ImGroup> updateWrapper = new LambdaUpdateWrapper<>();
|
||||||
|
updateWrapper.eq(ImGroup::getId,groupId)
|
||||||
|
.set(ImGroup::getLastMessageId,lastMessageId);
|
||||||
|
imGroupMapper.update(updateWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupProfileVO getGroupProfile(Long groupId) {
|
||||||
|
Long userId = UserContext.getUserId();
|
||||||
|
|
||||||
|
return imGroupMapper.selectGroupProfile(groupId,userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+25
-1
@@ -21,7 +21,7 @@ public class ImGroupUserService extends ServiceImpl<ImGroupUserMapper, ImGroupUs
|
|||||||
private ImGroupUserMapper imGroupUserMapper;
|
private ImGroupUserMapper imGroupUserMapper;
|
||||||
|
|
||||||
// 获取群组在线用户列表
|
// 获取群组在线用户列表
|
||||||
public List<Long> getOnlineGroupUsers(Long userId) {
|
public List<Long> getAllOnlineGroupUsers(Long userId) {
|
||||||
// 1️⃣ 查询用户所在的群组ID列表
|
// 1️⃣ 查询用户所在的群组ID列表
|
||||||
LambdaQueryWrapper<ImGroupUser> groupWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<ImGroupUser> groupWrapper = new LambdaQueryWrapper<>();
|
||||||
groupWrapper.eq(ImGroupUser::getUserId, userId)
|
groupWrapper.eq(ImGroupUser::getUserId, userId)
|
||||||
@@ -48,6 +48,19 @@ public class ImGroupUserService extends ServiceImpl<ImGroupUserMapper, ImGroupUs
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Long> getGroupOnlineUserIds(Long groupId) {
|
||||||
|
LambdaQueryWrapper<ImGroupUser> groupWrapper = new LambdaQueryWrapper<>();
|
||||||
|
groupWrapper.eq(ImGroupUser::getGroupId, groupId)
|
||||||
|
.select(ImGroupUser::getUserId);
|
||||||
|
List<ImGroupUser> groupMembers = imGroupUserMapper.selectList(groupWrapper);
|
||||||
|
|
||||||
|
return groupMembers.stream()
|
||||||
|
.map(ImGroupUser::getUserId)
|
||||||
|
.filter(SessionManager::isOnline)
|
||||||
|
.distinct() // 去重
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
public void decreaseUnreadCount(Long groupId,Long userId){
|
public void decreaseUnreadCount(Long groupId,Long userId){
|
||||||
LambdaUpdateWrapper<ImGroupUser> updateWrapper = new LambdaUpdateWrapper<>();
|
LambdaUpdateWrapper<ImGroupUser> updateWrapper = new LambdaUpdateWrapper<>();
|
||||||
|
|
||||||
@@ -70,4 +83,15 @@ public class ImGroupUserService extends ServiceImpl<ImGroupUserMapper, ImGroupUs
|
|||||||
|
|
||||||
return queryGroupUserVOS;
|
return queryGroupUserVOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateGroupUnreadCount(Long groupId, Long excludeUserId) {
|
||||||
|
LambdaUpdateWrapper<ImGroupUser> updateWrapper = new LambdaUpdateWrapper<>();
|
||||||
|
updateWrapper
|
||||||
|
.eq(ImGroupUser::getGroupId, groupId)
|
||||||
|
.ne(ImGroupUser::getUserId, excludeUserId)
|
||||||
|
.setSql("b_unread_count = b_unread_count + 1");
|
||||||
|
|
||||||
|
imGroupUserMapper.update(updateWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+11
-2
@@ -9,12 +9,10 @@
|
|||||||
SELECT *
|
SELECT *
|
||||||
FROM (
|
FROM (
|
||||||
SELECT
|
SELECT
|
||||||
f.b_id AS id,
|
|
||||||
f.b_friend_id AS friendId,
|
f.b_friend_id AS friendId,
|
||||||
u.b_name AS friendName,
|
u.b_name AS friendName,
|
||||||
u.b_avatar AS friendAvatar,
|
u.b_avatar AS friendAvatar,
|
||||||
f.b_unread_count AS unreadCount,
|
f.b_unread_count AS unreadCount,
|
||||||
m.b_id AS lastMessageId,
|
|
||||||
m.b_send_time AS lastMessageTime,
|
m.b_send_time AS lastMessageTime,
|
||||||
m.b_type AS lastMessageType,
|
m.b_type AS lastMessageType,
|
||||||
m.b_content AS lastMessageContent,
|
m.b_content AS lastMessageContent,
|
||||||
@@ -63,4 +61,15 @@
|
|||||||
WHERE b_user_id = #{userId} and b_friend_id = #{friendId}
|
WHERE b_user_id = #{userId} and b_friend_id = #{friendId}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
|
||||||
|
<select id="selectFriendProfile" resultType="cn.link56.im.model.vo.FriendProfileVO">
|
||||||
|
SELECT
|
||||||
|
f.b_friend_id AS friendId,
|
||||||
|
u.b_name AS friendName,
|
||||||
|
u.b_avatar AS friendAvatar,
|
||||||
|
f.b_unread_count AS unreadCount
|
||||||
|
FROM b_im_friend f
|
||||||
|
INNER JOIN b_company_user u ON f.b_friend_id = u.b_id
|
||||||
|
WHERE f.b_user_id = #{userId} AND f.b_friend_id = #{friendId}
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
+15
-3
@@ -14,12 +14,10 @@
|
|||||||
g.b_avatar AS groupAvatar,
|
g.b_avatar AS groupAvatar,
|
||||||
gu.b_unread_count AS unreadCount,
|
gu.b_unread_count AS unreadCount,
|
||||||
|
|
||||||
m.b_id AS lastMessageId,
|
|
||||||
m.b_send_time AS lastMessageTime,
|
m.b_send_time AS lastMessageTime,
|
||||||
m.b_type AS lastMessageType,
|
m.b_type AS lastMessageType,
|
||||||
m.b_content AS lastMessageContent,
|
m.b_content AS lastMessageContent,
|
||||||
|
|
||||||
u.b_id AS lastMessageSenderId,
|
|
||||||
u.b_name AS lastMessageSenderName,
|
u.b_name AS lastMessageSenderName,
|
||||||
|
|
||||||
ROW_NUMBER() OVER (
|
ROW_NUMBER() OVER (
|
||||||
@@ -29,7 +27,7 @@
|
|||||||
) AS rn
|
) AS rn
|
||||||
FROM b_im_group g
|
FROM b_im_group g
|
||||||
INNER JOIN b_im_group_user gu ON g.b_id = gu.b_group_id
|
INNER JOIN b_im_group_user gu ON g.b_id = gu.b_group_id
|
||||||
LEFT JOIN b_im_group_message m ON gu.b_last_message_id = m.b_id
|
LEFT JOIN b_im_group_message m ON g.b_last_message_id = m.b_id
|
||||||
LEFT JOIN b_company_user u ON m.b_sender_id = u.b_id
|
LEFT JOIN b_company_user u ON m.b_sender_id = u.b_id
|
||||||
WHERE gu.b_user_id = #{userId}
|
WHERE gu.b_user_id = #{userId}
|
||||||
<if test="name != null and name != ''">
|
<if test="name != null and name != ''">
|
||||||
@@ -51,4 +49,18 @@
|
|||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
<select id="selectGroupProfile"
|
||||||
|
resultType="cn.link56.im.model.vo.GroupProfileVO">
|
||||||
|
SELECT
|
||||||
|
g.b_id AS groupId,
|
||||||
|
g.b_name AS groupName,
|
||||||
|
g.b_avatar AS groupAvatar,
|
||||||
|
gu.b_unread_count AS unreadCount
|
||||||
|
FROM b_im_group g
|
||||||
|
INNER JOIN b_im_group_user gu ON g.b_id = gu.b_group_id
|
||||||
|
WHERE gu.b_user_id = #{userId}
|
||||||
|
AND g.b_id = #{groupId}
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { CreateFriendParams, ImFriend, ImGroup, ImGroupMessage, ImGroupUser, ImPrivateMessage, QueryFriendParams, QueryGroupMessageParams, QueryGroupParams, QueryGroupUserParams, QueryPrivateMessageParams, UpdateGroupUnreadParams, UpdatePrivateUnreadParams } from '@/types/im'
|
import type { CreateFriendParams, ImFriend, ImFriendProfile, ImGroup, ImGroupMessage, ImGroupProfile, ImGroupUser, ImPrivateMessage, QueryFriendParams, QueryGroupMessageParams, QueryGroupParams, QueryGroupUserParams, QueryPrivateMessageParams, UpdateGroupUnreadParams, UpdatePrivateUnreadParams } from '@/types/im'
|
||||||
import { httpPostJson } from '@/request/utils'
|
import { httpGet, httpPostJson } from '@/request/utils'
|
||||||
|
|
||||||
export function createFriendApi(params: CreateFriendParams) {
|
export function createFriendApi(params: CreateFriendParams) {
|
||||||
return httpPostJson<void>(`/im/friend/create`, params)
|
return httpPostJson<void>(`/im/friend/create`, params)
|
||||||
@@ -31,3 +31,11 @@ export function updatePrivateUnreadApi(params: UpdatePrivateUnreadParams) {
|
|||||||
export function queryGroupUserApi(params: QueryGroupUserParams) {
|
export function queryGroupUserApi(params: QueryGroupUserParams) {
|
||||||
return httpPostJson<ImGroupUser[]>('/im/group/user/query', params)
|
return httpPostJson<ImGroupUser[]>('/im/group/user/query', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getFriendProfileApi(friendId: number) {
|
||||||
|
return httpGet<ImFriendProfile>(`/im/friend/${friendId}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGroupProfileApi(groupId: number) {
|
||||||
|
return httpGet<ImGroupProfile>(`/im/group/${groupId}`)
|
||||||
|
}
|
||||||
@@ -256,7 +256,7 @@ function createWebSocket(options?: Partial<UseWebSocketOptions>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sendGroup(groupId: number, content: any) {
|
function sendGroup(groupId: number, content: any) {
|
||||||
send(MessageType.GROUP, { groupId, content })
|
send(MessageType.GROUP, content, groupId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================== 初始化 ================== */
|
/* ================== 初始化 ================== */
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ export enum MessageType {
|
|||||||
|
|
||||||
PRIVATE = 8,
|
PRIVATE = 8,
|
||||||
GROUP = 9,
|
GROUP = 9,
|
||||||
FRIEND_UPDATE = 10,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageRequest {
|
export interface MessageRequest {
|
||||||
@@ -48,15 +47,12 @@ export interface QueryFriendParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ImFriend {
|
export interface ImFriend {
|
||||||
id: number
|
|
||||||
|
|
||||||
friendId: number
|
friendId: number
|
||||||
friendName: string
|
friendName: string
|
||||||
friendAvatar: string
|
friendAvatar: string
|
||||||
|
|
||||||
unreadCount: number
|
unreadCount: number
|
||||||
|
|
||||||
lastMessageId: number
|
|
||||||
lastMessageTime: number
|
lastMessageTime: number
|
||||||
lastMessageType: number
|
lastMessageType: number
|
||||||
lastMessageContent: string
|
lastMessageContent: string
|
||||||
@@ -79,12 +75,10 @@ export interface ImGroup {
|
|||||||
|
|
||||||
unreadCount: number
|
unreadCount: number
|
||||||
|
|
||||||
lastMessageId: number
|
|
||||||
lastMessageTime: number
|
lastMessageTime: number
|
||||||
lastMessageType: number
|
lastMessageType: number
|
||||||
lastMessageContent: string
|
lastMessageContent: string
|
||||||
|
|
||||||
lastMessageSenderId: number
|
|
||||||
lastMessageSenderName: string
|
lastMessageSenderName: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,3 +146,17 @@ export interface ImGroupUser {
|
|||||||
userName: string
|
userName: string
|
||||||
isOnline: boolean
|
isOnline: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ImFriendProfile {
|
||||||
|
friendId: number
|
||||||
|
friendName: string
|
||||||
|
friendAvatar: string
|
||||||
|
unreadCount: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImGroupProfile {
|
||||||
|
groupId: number
|
||||||
|
groupName: string
|
||||||
|
groupAvatar: string
|
||||||
|
unreadCount: number
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import { useScrollWatcher } from '@/hooks/useScrollWatcher'
|
|||||||
import { queryGroupMessageApi, queryGroupUserApi } from '@/request/api/im'
|
import { queryGroupMessageApi, queryGroupUserApi } from '@/request/api/im'
|
||||||
import { useUserStore } from '@/store/user'
|
import { useUserStore } from '@/store/user'
|
||||||
import { useWebSocket } from '@/store/websocket'
|
import { useWebSocket } from '@/store/websocket'
|
||||||
|
import { MessageType } from '@/types/im'
|
||||||
import { formatImTime } from '@/utils/time'
|
import { formatImTime } from '@/utils/time'
|
||||||
import { generateUUID } from '@/utils/uuid'
|
import { generateUUID } from '@/utils/uuid'
|
||||||
|
|
||||||
@@ -22,6 +23,40 @@ onMounted(() => {
|
|||||||
|
|
||||||
websocket.onMessage(async (msg) => {
|
websocket.onMessage(async (msg) => {
|
||||||
const { from, type, data } = msg
|
const { from, type, data } = msg
|
||||||
|
|
||||||
|
if (type === MessageType.GROUP) {
|
||||||
|
// 自己发的
|
||||||
|
if (userId === data.senderId) {
|
||||||
|
messages.value.forEach((item) => {
|
||||||
|
if (item._tempId === data.tempId) {
|
||||||
|
item._status = 'sent'
|
||||||
|
item._tempId = ''
|
||||||
|
item.id = data.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (props.group.groupId === from) {
|
||||||
|
const newData: ImGroupMessage = {
|
||||||
|
id: data.id,
|
||||||
|
groupId: data.groupId,
|
||||||
|
senderId: data.senderId,
|
||||||
|
senderName: data.senderName,
|
||||||
|
senderAvatar: data.senderAvatar,
|
||||||
|
content: data.content,
|
||||||
|
type: data.type,
|
||||||
|
sendTime: data.sendTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
messages.value.push(newData)
|
||||||
|
// 更新未读数量,交给外部
|
||||||
|
|
||||||
|
// 等待 DOM 更新再滚动到底部
|
||||||
|
await nextTick()
|
||||||
|
scrollToLatestMessage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -52,6 +87,7 @@ watch(
|
|||||||
pagination.value = { pageSize: 10, loading: false, hasMore: true }
|
pagination.value = { pageSize: 10, loading: false, hasMore: true }
|
||||||
loadMessages('down')
|
loadMessages('down')
|
||||||
|
|
||||||
|
groupUsers.value = []
|
||||||
loadGroupUsers()
|
loadGroupUsers()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -106,8 +142,6 @@ async function loadMessages(direction = 'down') {
|
|||||||
|
|
||||||
pagination.value.loading = true
|
pagination.value.loading = true
|
||||||
|
|
||||||
const userId = userStore.user.id
|
|
||||||
|
|
||||||
let beforeTimestamp: number | null = null
|
let beforeTimestamp: number | null = null
|
||||||
let beforeId: number | null = null
|
let beforeId: number | null = null
|
||||||
|
|
||||||
@@ -197,39 +231,44 @@ async function sendMessage() {
|
|||||||
ElMessage.warning('发送消息不能为空')
|
ElMessage.warning('发送消息不能为空')
|
||||||
}
|
}
|
||||||
|
|
||||||
// const userId = userStore.user.id
|
const userId = userStore.user.id
|
||||||
// const _tempId = generateUUID()
|
const groupId = props.group.groupId
|
||||||
|
const _tempId = generateUUID()
|
||||||
|
|
||||||
// const localMessage: ImPrivateMessage = {
|
const localMessage: ImGroupMessage = {
|
||||||
// id: -Date.now(),
|
id: -Date.now(),
|
||||||
// senderId: userId,
|
groupId,
|
||||||
// receiverId: props.friend.friendId,
|
senderId: userId,
|
||||||
// content,
|
senderAvatar: userStore.user.avatar,
|
||||||
// type: 0,
|
senderName: userStore.user.name,
|
||||||
// sendTime: Date.now(),
|
content,
|
||||||
// _tempId,
|
type: 0,
|
||||||
// _status: 'sending',
|
sendTime: Date.now(),
|
||||||
// }
|
_tempId,
|
||||||
|
_status: 'sending',
|
||||||
|
}
|
||||||
|
|
||||||
// messages.value.push(localMessage)
|
messages.value.push(localMessage)
|
||||||
|
|
||||||
// // 清空输入框
|
// 清空输入框
|
||||||
// if (chatInputRef.value) {
|
if (chatInputRef.value) {
|
||||||
// chatInputRef.value.innerHTML = ''
|
chatInputRef.value.innerHTML = ''
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const privateData: any = {
|
const sentData: any = {
|
||||||
// content,
|
content,
|
||||||
// type: 0,
|
type: 0,
|
||||||
// tempId: _tempId,
|
tempId: _tempId,
|
||||||
// }
|
senderAvatar: userStore.user.avatar,
|
||||||
|
senderName: userStore.user.name,
|
||||||
|
}
|
||||||
|
|
||||||
// websocket.sendPrivate(props.friend.friendId, privateData)
|
websocket.sendGroup(groupId, sentData)
|
||||||
|
|
||||||
// chatInputValue.value = ''
|
chatInputValue.value = ''
|
||||||
// // 等待 DOM 更新再滚动到底部
|
// 等待 DOM 更新再滚动到底部
|
||||||
// await nextTick()
|
await nextTick()
|
||||||
// scrollToLatestMessage()
|
scrollToLatestMessage()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { ImFriend, ImGroup } from '@/types/im'
|
|||||||
import { Search } from '@element-plus/icons-vue'
|
import { Search } from '@element-plus/icons-vue'
|
||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { queryFriendApi, queryGroupApi, updateGroupUnreadApi, updatePrivateUnreadApi } from '@/request/api/im'
|
import { getFriendProfileApi, getGroupProfileApi, queryFriendApi, queryGroupApi, updateGroupUnreadApi, updatePrivateUnreadApi } from '@/request/api/im'
|
||||||
import { useUserStore } from '@/store/user'
|
import { useUserStore } from '@/store/user'
|
||||||
import { useWebSocket } from '@/store/websocket'
|
import { useWebSocket } from '@/store/websocket'
|
||||||
import { MessageType } from '@/types/im'
|
import { MessageType } from '@/types/im'
|
||||||
@@ -78,7 +78,7 @@ onMounted(() => {
|
|||||||
loadGroups()
|
loadGroups()
|
||||||
loadFriends()
|
loadFriends()
|
||||||
|
|
||||||
websocket.onMessage((msg) => {
|
websocket.onMessage(async (msg) => {
|
||||||
const { type, from, data } = msg
|
const { type, from, data } = msg
|
||||||
|
|
||||||
// 更新在线状态
|
// 更新在线状态
|
||||||
@@ -94,55 +94,164 @@ onMounted(() => {
|
|||||||
else if (type === MessageType.OFFLINE) {
|
else if (type === MessageType.OFFLINE) {
|
||||||
updateOnlineStatus(false)
|
updateOnlineStatus(false)
|
||||||
}
|
}
|
||||||
else if (type === MessageType.FRIEND_UPDATE) {
|
|
||||||
const updatedFriend = data as ImFriend
|
|
||||||
|
|
||||||
// 检查是否已经存在
|
|
||||||
const exists = friendState.value.list.some(
|
|
||||||
item => item.friendId === updatedFriend.friendId,
|
|
||||||
)
|
|
||||||
|
|
||||||
// 如果不存在,放到第一个
|
|
||||||
if (!exists) {
|
|
||||||
friendState.value.list.unshift(updatedFriend)
|
|
||||||
friendState.value.total += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (type === MessageType.PRIVATE) {
|
else if (type === MessageType.PRIVATE) {
|
||||||
const chatFriendId = currentFriendChat.value?.friendId
|
const chatFriendId = currentFriendChat.value?.friendId
|
||||||
const { senderId, receiverId, type: contentType, content, sendTime } = data
|
const { senderId, receiverId, type: contentType, content, sendTime } = data
|
||||||
|
|
||||||
// 遍历好友列表更新最近消息和未读
|
// 私聊中,对方一定是 sender 或 receiver
|
||||||
friendState.value.list.forEach((item) => {
|
const targetFriendId = senderId === userId ? receiverId : senderId
|
||||||
if (item.friendId === senderId || item.friendId === receiverId) {
|
|
||||||
|
// 先找本地好友
|
||||||
|
const friend = friendState.value.list.find(
|
||||||
|
item => item.friendId === targetFriendId,
|
||||||
|
)
|
||||||
|
|
||||||
|
// 如果本地不存在,按需拉取
|
||||||
|
if (!friend) {
|
||||||
|
try {
|
||||||
|
const res = await getFriendProfileApi(targetFriendId)
|
||||||
|
|
||||||
|
const newFriend: ImFriend = {
|
||||||
|
friendId: res.data.friendId,
|
||||||
|
friendAvatar: res.data.friendAvatar,
|
||||||
|
friendName: res.data.friendName,
|
||||||
|
unreadCount: res.data.unreadCount,
|
||||||
|
|
||||||
|
lastMessageTime: sendTime,
|
||||||
|
lastMessageContent: content,
|
||||||
|
lastMessageType: contentType,
|
||||||
|
|
||||||
|
isOnline: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
friendState.value.list.unshift(newFriend)
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error('getFriendProfileApi failed', e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!friend) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 更新最近消息
|
// 更新最近消息
|
||||||
item.lastMessageTime = sendTime
|
friend.lastMessageTime = sendTime
|
||||||
item.lastMessageContent = content
|
friend.lastMessageContent = content
|
||||||
item.lastMessageType = contentType
|
friend.lastMessageType = contentType
|
||||||
|
|
||||||
// 如果是别人发的消息并且不是当前聊天好友,增加未读
|
// 未读数处理
|
||||||
if (userId !== senderId && senderId !== chatFriendId && item.friendId === senderId) {
|
if (userId !== senderId && targetFriendId !== chatFriendId) {
|
||||||
item.unreadCount = (item.unreadCount || 0) + 1
|
friend.unreadCount = (friend.unreadCount || 0) + 1
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 更新当前聊天对象最近消息
|
// 当前聊天窗口
|
||||||
if (currentFriendChat.value && (senderId === chatFriendId || receiverId === chatFriendId)) {
|
if (currentFriendChat.value && chatFriendId === targetFriendId) {
|
||||||
currentFriendChat.value.lastMessageTime = sendTime
|
currentFriendChat.value.lastMessageTime = sendTime
|
||||||
currentFriendChat.value.lastMessageContent = content
|
currentFriendChat.value.lastMessageContent = content
|
||||||
currentFriendChat.value.lastMessageType = contentType
|
currentFriendChat.value.lastMessageType = contentType
|
||||||
|
|
||||||
// 重置未读数量,如果是别人发的消息且当前聊天窗口打开
|
|
||||||
if (userId !== senderId) {
|
if (userId !== senderId) {
|
||||||
currentFriendChat.value.unreadCount = 0
|
currentFriendChat.value.unreadCount = 0
|
||||||
// 调用接口同步重置
|
|
||||||
updatePrivateUnreadApi({
|
updatePrivateUnreadApi({
|
||||||
userId,
|
userId,
|
||||||
friendId: chatFriendId!,
|
friendId: chatFriendId!,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 永远置顶
|
||||||
|
const index = friendState.value.list.findIndex(
|
||||||
|
item => item.friendId === targetFriendId,
|
||||||
|
)
|
||||||
|
if (index > -1) {
|
||||||
|
const [f] = friendState.value.list.splice(index, 1)
|
||||||
|
friendState.value.list.unshift(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type === MessageType.GROUP) {
|
||||||
|
const {
|
||||||
|
groupId,
|
||||||
|
senderId,
|
||||||
|
senderName,
|
||||||
|
type: contentType,
|
||||||
|
content,
|
||||||
|
sendTime,
|
||||||
|
} = data
|
||||||
|
|
||||||
|
const currentGroupId = currentGroupChat.value?.groupId
|
||||||
|
|
||||||
|
// 1️⃣ 查找本地群
|
||||||
|
const group = groupState.value.list.find(
|
||||||
|
item => item.groupId === groupId,
|
||||||
|
)
|
||||||
|
|
||||||
|
// 2️⃣ 本地没有 → 懒加载群 Profile
|
||||||
|
if (!group) {
|
||||||
|
try {
|
||||||
|
const res = await getGroupProfileApi(groupId)
|
||||||
|
|
||||||
|
const newGroup: ImGroup = {
|
||||||
|
groupId: res.data.groupId,
|
||||||
|
groupAvatar: res.data.groupAvatar,
|
||||||
|
groupName: res.data.groupName,
|
||||||
|
unreadCount: res.data.unreadCount,
|
||||||
|
|
||||||
|
lastMessageTime: sendTime,
|
||||||
|
lastMessageContent: content,
|
||||||
|
lastMessageType: contentType,
|
||||||
|
|
||||||
|
lastMessageSenderName: senderName,
|
||||||
|
}
|
||||||
|
|
||||||
|
groupState.value.list.unshift(newGroup)
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error('getGroupProfileApi failed', e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!group) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 3️⃣ 更新最近消息
|
||||||
|
group.lastMessageTime = sendTime
|
||||||
|
group.lastMessageContent = content
|
||||||
|
group.lastMessageType = contentType
|
||||||
|
group.lastMessageSenderName = senderName
|
||||||
|
|
||||||
|
// 4️⃣ 未读处理(不是自己 & 当前群未打开)
|
||||||
|
if (senderId !== userId && groupId !== currentGroupId) {
|
||||||
|
group.unreadCount = (group.unreadCount || 0) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5️⃣ 当前群窗口处理
|
||||||
|
if (currentGroupChat.value && currentGroupId === groupId) {
|
||||||
|
currentGroupChat.value.lastMessageTime = sendTime
|
||||||
|
currentGroupChat.value.lastMessageContent = content
|
||||||
|
currentGroupChat.value.lastMessageType = contentType
|
||||||
|
currentGroupChat.value.lastMessageSenderName = senderName
|
||||||
|
|
||||||
|
if (senderId !== userId) {
|
||||||
|
currentGroupChat.value.unreadCount = 0
|
||||||
|
|
||||||
|
updateGroupUnreadApi({
|
||||||
|
userId,
|
||||||
|
groupId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6️⃣ 永远置顶
|
||||||
|
const index = groupState.value.list.findIndex(
|
||||||
|
item => item.groupId === groupId,
|
||||||
|
)
|
||||||
|
if (index > -1) {
|
||||||
|
const [g] = groupState.value.list.splice(index, 1)
|
||||||
|
groupState.value.list.unshift(g)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -342,7 +451,7 @@ function onGroupChat(group: ImGroup) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="im__list-body">
|
<div class="im__list-body">
|
||||||
<div
|
<div
|
||||||
v-for="item in friendState.list" :key="item.id" class="im__chat-item"
|
v-for="item in friendState.list" :key="item.friendId" class="im__chat-item"
|
||||||
:class="{
|
:class="{
|
||||||
'im__chat-item--selected':
|
'im__chat-item--selected':
|
||||||
isPrivateChat && item.friendId === currentFriendChat?.friendId,
|
isPrivateChat && item.friendId === currentFriendChat?.friendId,
|
||||||
@@ -411,8 +520,11 @@ function onGroupChat(group: ImGroup) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="im__chat-item-message">
|
<div class="im__chat-item-message">
|
||||||
<div v-if="item.lastMessageId" class="im__chat-item-last-message">
|
<div class="im__chat-item-last-message">
|
||||||
{{ item.lastMessageSenderName }}:{{ item.lastMessageContent }}
|
<template v-if="item.lastMessageSenderName">
|
||||||
|
{{ item.lastMessageSenderName }}:
|
||||||
|
</template>
|
||||||
|
{{ item.lastMessageContent }}
|
||||||
</div>
|
</div>
|
||||||
<el-badge :value="item.unreadCount || 0" :show-zero="false" :max="99" class="im__chat-item-unread-count" />
|
<el-badge :value="item.unreadCount || 0" :show-zero="false" :max="99" class="im__chat-item-unread-count" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in new issue
Block a user