diff --git a/im-platform/src/main/java/com/bx/implatform/entity/User.java b/im-platform/src/main/java/com/bx/implatform/entity/User.java index 0cf0c10..a943825 100644 --- a/im-platform/src/main/java/com/bx/implatform/entity/User.java +++ b/im-platform/src/main/java/com/bx/implatform/entity/User.java @@ -114,5 +114,14 @@ public class User { */ private String uniqueToken; + /** + * 标签ID + */ + private String labelIds; + + /** + * 分组ID + */ + private String groupIds; } diff --git a/im-platform/src/main/java/com/bx/implatform/entity/UserGroup.java b/im-platform/src/main/java/com/bx/implatform/entity/UserGroup.java new file mode 100644 index 0000000..9be1b9f --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/entity/UserGroup.java @@ -0,0 +1,25 @@ +package com.bx.implatform.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + *

+ * 标签分组 + *

+ * + * @author blue + * @since 2022-10-01 + */ +@Data +@TableName("im_user_group") +public class UserGroup { + + @TableId(type = IdType.AUTO) + private Long id; + + private String groupName; + +} diff --git a/im-platform/src/main/java/com/bx/implatform/entity/UserLabel.java b/im-platform/src/main/java/com/bx/implatform/entity/UserLabel.java new file mode 100644 index 0000000..b237a1a --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/entity/UserLabel.java @@ -0,0 +1,26 @@ +package com.bx.implatform.entity; +import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +/** + *

+ * 标签分组 + *

+ * + * @author blue + * @since 2022-10-01 + */ +@Data +@TableName("im_user_label") +public class UserLabel { + + @TableId(type = IdType.AUTO) + private Long id; + + private String labelName; + +} diff --git a/im-platform/src/main/java/com/bx/implatform/mapper/UserGroupMapper.java b/im-platform/src/main/java/com/bx/implatform/mapper/UserGroupMapper.java new file mode 100644 index 0000000..be7edf3 --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/mapper/UserGroupMapper.java @@ -0,0 +1,9 @@ +package com.bx.implatform.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.bx.implatform.entity.UserGroup; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface UserGroupMapper extends BaseMapper { +} \ No newline at end of file diff --git a/im-platform/src/main/java/com/bx/implatform/mapper/UserLabelMapper.java b/im-platform/src/main/java/com/bx/implatform/mapper/UserLabelMapper.java new file mode 100644 index 0000000..488229c --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/mapper/UserLabelMapper.java @@ -0,0 +1,9 @@ +package com.bx.implatform.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.bx.implatform.entity.UserLabel; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface UserLabelMapper extends BaseMapper { +} \ No newline at end of file diff --git a/im-platform/src/main/java/com/bx/implatform/service/UserGroupService.java b/im-platform/src/main/java/com/bx/implatform/service/UserGroupService.java new file mode 100644 index 0000000..261183f --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/service/UserGroupService.java @@ -0,0 +1,13 @@ +package com.bx.implatform.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bx.implatform.entity.UserGroup; +import java.util.List; + +public interface UserGroupService extends IService { + + /** + * 根据分组ID列表获取分组名称列表 + */ + List getGroupNamesByIds(String groupIds); +} \ No newline at end of file diff --git a/im-platform/src/main/java/com/bx/implatform/service/UserLabelService.java b/im-platform/src/main/java/com/bx/implatform/service/UserLabelService.java new file mode 100644 index 0000000..aeecf23 --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/service/UserLabelService.java @@ -0,0 +1,13 @@ +package com.bx.implatform.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bx.implatform.entity.UserLabel; +import java.util.List; + +public interface UserLabelService extends IService { + + /** + * 根据标签ID列表获取标签名称列表 + */ + List getLabelNamesByIds(String labelIds); +} \ No newline at end of file diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/UserGroupServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/UserGroupServiceImpl.java new file mode 100644 index 0000000..e9872a4 --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/service/impl/UserGroupServiceImpl.java @@ -0,0 +1,46 @@ +package com.bx.implatform.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bx.implatform.entity.UserGroup; +import com.bx.implatform.mapper.UserGroupMapper; +import com.bx.implatform.service.UserGroupService; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class UserGroupServiceImpl extends ServiceImpl implements UserGroupService { + + @Override + public List getGroupNamesByIds(String groupIds) { + if (!StringUtils.hasText(groupIds)) { + return Collections.emptyList(); + } + + // 将逗号分隔的ID字符串转换为Long列表 + List ids = Arrays.stream(groupIds.split(",")) + .map(String::trim) + .filter(StringUtils::hasText) + .map(Long::parseLong) + .collect(Collectors.toList()); + + if (ids.isEmpty()) { + return Collections.emptyList(); + } + + // 查询标签 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(UserGroup::getId, ids); + + List groups = this.list(wrapper); + + // 返回标签名称列表 + return groups.stream() + .map(UserGroup::getGroupName) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/UserLabelServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/UserLabelServiceImpl.java new file mode 100644 index 0000000..ba48564 --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/service/impl/UserLabelServiceImpl.java @@ -0,0 +1,46 @@ +package com.bx.implatform.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bx.implatform.entity.UserLabel; +import com.bx.implatform.mapper.UserLabelMapper; +import com.bx.implatform.service.UserLabelService; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class UserLabelServiceImpl extends ServiceImpl implements UserLabelService { + + @Override + public List getLabelNamesByIds(String labelIds) { + if (!StringUtils.hasText(labelIds)) { + return Collections.emptyList(); + } + + // 将逗号分隔的ID字符串转换为Long列表 + List ids = Arrays.stream(labelIds.split(",")) + .map(String::trim) + .filter(StringUtils::hasText) + .map(Long::parseLong) + .collect(Collectors.toList()); + + if (ids.isEmpty()) { + return Collections.emptyList(); + } + + // 查询标签 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(UserLabel::getId, ids); + + List labels = this.list(wrapper); + + // 返回标签名称列表 + return labels.stream() + .map(UserLabel::getLabelName) + .collect(Collectors.toList()); + } +} \ No newline at end of file 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 29e92c9..d12ff45 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 @@ -22,10 +22,7 @@ import com.bx.implatform.enums.ResultCode; import com.bx.implatform.exception.GlobalException; import com.bx.implatform.mapper.UserMapper; import com.bx.implatform.result.ResultUtils; -import com.bx.implatform.service.FriendService; -import com.bx.implatform.service.GroupMemberService; -import com.bx.implatform.service.PrivateMessageService; -import com.bx.implatform.service.UserService; +import com.bx.implatform.service.*; import com.bx.implatform.session.SessionContext; import com.bx.implatform.session.UserSession; import com.bx.implatform.util.BeanUtils; @@ -36,9 +33,11 @@ import com.bx.implatform.vo.OnlineTerminalVO; import com.bx.implatform.vo.UserVO; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; import java.util.*; import java.util.stream.Collectors; @@ -57,6 +56,10 @@ public class UserServiceImpl extends ServiceImpl implements Us private final IMClient imClient; private final SensitiveFilterUtil sensitiveFilterUtil; private final PrivateMessageService privateMessageService; + @Autowired + private UserLabelService userLabelService; + @Autowired + private UserGroupService UserGroupService; // @Override // public LoginVO login(LoginDTO dto) { @@ -317,8 +320,24 @@ public class UserServiceImpl extends ServiceImpl implements Us @Override public UserVO findUserById(Long id) { User user = this.getById(id); + if (user == null) { + return null; + } + UserVO vo = BeanUtils.copyProperties(user, UserVO.class); vo.setOnline(imClient.isOnline(id)); + + // 转换标签ID为标签名称 + if (StringUtils.hasText(user.getLabelIds())) { + List labelNames = userLabelService.getLabelNamesByIds(user.getLabelIds()); + vo.setLabelNames(labelNames); + } + + if (StringUtils.hasText(user.getGroupIds())) { + List groupNames = UserGroupService.getGroupNamesByIds(user.getGroupIds()); + vo.setGroupNames(groupNames); + } + return vo; } diff --git a/im-platform/src/main/java/com/bx/implatform/vo/UserVO.java b/im-platform/src/main/java/com/bx/implatform/vo/UserVO.java index 64ccae5..c53dcd1 100644 --- a/im-platform/src/main/java/com/bx/implatform/vo/UserVO.java +++ b/im-platform/src/main/java/com/bx/implatform/vo/UserVO.java @@ -5,6 +5,7 @@ import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; import org.hibernate.validator.constraints.Length; +import java.util.List; @Data @Schema(description = "用户信息VO") @@ -48,4 +49,20 @@ public class UserVO { @Schema(description = "被封禁原因") private String reason; -} + + @Schema(description = "用户IP") + private String lastLoginIp; + + @Schema(description = "来源地址") + private String sourceUrl; + + @Schema(description = "标签ID列表") + private String labelIds; + + @Schema(description = "标签名称列表") + private List labelNames; + + @Schema(description = "分组名称列表") + private List groupNames; + +} \ No newline at end of file diff --git a/im-web/src/components/chat/ChatBox.vue b/im-web/src/components/chat/ChatBox.vue index 5111d13..fe59c12 100644 --- a/im-web/src/components/chat/ChatBox.vue +++ b/im-web/src/components/chat/ChatBox.vue @@ -4,6 +4,7 @@ {{ title }} + @@ -72,6 +73,61 @@ + @@ -130,6 +186,7 @@ export default { isReceipt: true, showRecord: false, // 是否显示语音录制弹窗 showSide: false, // 是否显示群聊信息栏 + showUserSide: false, // 是否显示用户信息栏 showHistory: false, // 是否显示历史聊天记录 showChangeCustomer: false, // 是否显示转接客服弹窗 lockMessage: false, // 是否锁定发送, @@ -280,6 +337,7 @@ export default { }, onCloseSide() { this.showSide = false; + this.showUserSide = false; }, onScrollToTop() { // 多展示10条信息 @@ -631,9 +689,11 @@ export default { method: 'GET' }).then((userInfo) => { this.userInfo = userInfo; + console.log(this.userInfo); this.updateFriendInfo(); }) }, + showName(msgInfo) { if (!msgInfo) { return "" @@ -843,6 +903,7 @@ export default { // 滚到底部 this.scrollToBottom(); this.showSide = false; + this.showUserSide = false; // 消息已读 this.readedMessage() // 初始状态只显示30条消息 @@ -1010,5 +1071,72 @@ export default { border-left: var(--im-border); } + .user-info-side { + .user-info-container { + padding: 20px; + height: 100%; + overflow-y: auto; + + .user-info-header { + text-align: center; + padding-bottom: 20px; + border-bottom: 1px solid #eee; + + .user-avatar-large { + width: 100px; + height: 100px; + border-radius: 50%; + object-fit: cover; + margin-bottom: 15px; + } + + .user-nickname { + font-size: 18px; + font-weight: 600; + margin: 10px 0 5px; + color: #333; + } + + .user-username { + font-size: 14px; + color: #999; + margin: 0; + } + } + + .user-info-content { + padding: 20px 0; + + .info-item { + display: flex; + padding: 10px 0; + border-bottom: 1px solid #f0f0f0; + + .info-label { + width: 70px; + font-size: 14px; + color: #999; + flex-shrink: 0; + } + + .info-value { + flex: 1; + font-size: 14px; + color: #333; + word-break: break-all; + /* 标签容器样式 */ + .el-tag { + margin-right: 8px; + margin-bottom: 8px; + + &:last-child { + margin-right: 0; + } + } + } + } + } + } + } } \ No newline at end of file diff --git a/im-web/src/components/setting/Setting.vue b/im-web/src/components/setting/Setting.vue index ea907be..e380269 100644 --- a/im-web/src/components/setting/Setting.vue +++ b/im-web/src/components/setting/Setting.vue @@ -246,9 +246,9 @@ export default { }); const loading = this.$loading({ - lock: true, - text: '正在切换账号...', - spinner: 'el-icon-loading' + lock: true, + text: '正在切换账号...', + spinner: 'el-icon-loading' }); const res = await this.$http({