From 4a8933961157f025c3381c68926bb1ebd3168c3a Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Sun, 12 Nov 2023 12:24:45 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BE=A4=E8=81=8A@=E5=8A=9F=E8=83=BD(=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E4=B8=AD)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bx/implatform/dto/GroupMessageDTO.java | 9 +- .../bx/implatform/entity/GroupMessage.java | 11 ++ .../service/IGroupMemberService.java | 1 - .../service/impl/GroupMessageServiceImpl.java | 38 +++--- .../com/bx/implatform/vo/GroupMessageVO.java | 7 ++ im-platform/src/main/resources/db/db.sql | 2 + im-ui/src/components/chat/ChatAtBox.vue | 44 ++++--- im-ui/src/components/chat/ChatBox.vue | 50 ++++---- im-ui/src/components/chat/ChatItem.vue | 81 +++++++++---- im-ui/src/store/chatStore.js | 13 +++ im-ui/src/store/friendStore.js | 1 + im-ui/src/view/Chat.vue | 30 ++--- im-ui/src/view/Friend.vue | 109 +++++++++++------- im-ui/src/view/Group.vue | 94 +++++++-------- im-ui/src/view/Home.vue | 9 +- 15 files changed, 314 insertions(+), 185 deletions(-) diff --git a/im-platform/src/main/java/com/bx/implatform/dto/GroupMessageDTO.java b/im-platform/src/main/java/com/bx/implatform/dto/GroupMessageDTO.java index 2535784..2b0ce80 100644 --- a/im-platform/src/main/java/com/bx/implatform/dto/GroupMessageDTO.java +++ b/im-platform/src/main/java/com/bx/implatform/dto/GroupMessageDTO.java @@ -7,6 +7,8 @@ import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.util.List; @Data @ApiModel("群聊消息DTO") @@ -16,8 +18,7 @@ public class GroupMessageDTO { @ApiModelProperty(value = "群聊id") private Long groupId; - - @Length(max=1024,message = "内容长度不得大于1024") + @Length(max=1024,message = "发送内容长度不得大于1024") @NotEmpty(message="发送内容不可为空") @ApiModelProperty(value = "发送内容") private String content; @@ -25,4 +26,8 @@ public class GroupMessageDTO { @NotNull(message="消息类型不可为空") @ApiModelProperty(value = "消息类型") private Integer type; + + @Size(max = 20,message = "一次最多只能@20个小伙伴哦") + @ApiModelProperty(value = "被@用户列表") + private List atUserIds; } diff --git a/im-platform/src/main/java/com/bx/implatform/entity/GroupMessage.java b/im-platform/src/main/java/com/bx/implatform/entity/GroupMessage.java index a94bec1..fa5fb28 100644 --- a/im-platform/src/main/java/com/bx/implatform/entity/GroupMessage.java +++ b/im-platform/src/main/java/com/bx/implatform/entity/GroupMessage.java @@ -44,6 +44,17 @@ public class GroupMessage extends Model { @TableField("send_id") private Long sendId; + /** + * 发送用户昵称 + */ + @TableField("send_nick_name") + private String sendNickName; + + /** + * @用户列表 + */ + @TableField("at_user_ids") + private String atUserIds; /** * 发送内容 */ diff --git a/im-platform/src/main/java/com/bx/implatform/service/IGroupMemberService.java b/im-platform/src/main/java/com/bx/implatform/service/IGroupMemberService.java index 3611045..a4966c0 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/IGroupMemberService.java +++ b/im-platform/src/main/java/com/bx/implatform/service/IGroupMemberService.java @@ -18,7 +18,6 @@ public interface IGroupMemberService extends IService { List findUserIdsByGroupId(Long groupId); - boolean saveOrUpdateBatch(Long groupId,List members); void removeByGroupId(Long groupId); diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java index d13bf57..3bab80d 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java +++ b/im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java @@ -4,12 +4,10 @@ import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; 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.implatform.entity.PrivateMessage; import com.bx.implatform.util.DateTimeUtils; import com.bx.implatform.vo.GroupMessageVO; import com.bx.imcommon.model.IMGroupMessage; @@ -30,16 +28,13 @@ import com.bx.implatform.session.SessionContext; import com.bx.implatform.session.UserSession; import com.bx.implatform.util.BeanUtils; import com.bx.implatform.dto.GroupMessageDTO; +import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.stream.Collectors; @Slf4j @@ -64,26 +59,33 @@ public class GroupMessageServiceImpl extends ServiceImpl userIds = groupMemberService.findUserIdsByGroupId(group.getId()); - if (!userIds.contains(session.getUserId())) { - throw new GlobalException(ResultCode.PROGRAM_ERROR, "您已不在群聊里面,无法发送消息"); + // 是否在群聊里面 + GroupMember member = groupMemberService.findByGroupAndUserId(dto.getGroupId(), session.getUserId()); + if (Objects.isNull(member)) { + throw new GlobalException(ResultCode.PROGRAM_ERROR, "您已不在群聊里面,无法撤回消息"); } + // 群聊成员列表 + List userIds = groupMemberService.findUserIdsByGroupId(group.getId()); + // 不用发给自己 + userIds = userIds.stream().filter(id -> !session.getUserId().equals(id)).collect(Collectors.toList()); // 保存消息 GroupMessage msg = BeanUtils.copyProperties(dto, GroupMessage.class); msg.setSendId(session.getUserId()); msg.setSendTime(new Date()); + msg.setSendNickName(member.getAliasName()); + if(CollectionUtil.isNotEmpty(dto.getAtUserIds())){ + msg.setAtUserIds(StrUtil.join(",",dto.getAtUserIds())); + } this.save(msg); - // 不用发给自己 - userIds = userIds.stream().filter(id -> !session.getUserId().equals(id)).collect(Collectors.toList()); // 群发 GroupMessageVO msgInfo = BeanUtils.copyProperties(msg, GroupMessageVO.class); + msgInfo.setAtUserIds(dto.getAtUserIds()); IMGroupMessage sendMessage = new IMGroupMessage<>(); sendMessage.setSender(new IMUserInfo(session.getUserId(), session.getTerminal())); sendMessage.setRecvIds(userIds); @@ -215,7 +217,13 @@ public class GroupMessageServiceImpl extends ServiceImpl messages = this.list(wrapper); // 转成vo - List vos = messages.stream().map(m -> BeanUtils.copyProperties(m, GroupMessageVO.class)).collect(Collectors.toList()); + List vos = messages.stream().map(m -> { + GroupMessageVO vo = BeanUtils.copyProperties(m, GroupMessageVO.class); + // 被@用户列表 + List atIds = Arrays.asList(StrUtil.split(m.getAtUserIds(),",")); + vo.setAtUserIds(atIds.stream().map(id->Long.parseLong(id)).collect(Collectors.toList())); + return vo; + }).collect(Collectors.toList()); // 消息状态,数据库没有存群聊的消息状态,需要从redis取 List keys = ids.stream() .map(id -> String.join(":", RedisKey.IM_GROUP_READED_POSITION, id.toString(), session.getUserId().toString())) diff --git a/im-platform/src/main/java/com/bx/implatform/vo/GroupMessageVO.java b/im-platform/src/main/java/com/bx/implatform/vo/GroupMessageVO.java index f00cccc..1f5beae 100644 --- a/im-platform/src/main/java/com/bx/implatform/vo/GroupMessageVO.java +++ b/im-platform/src/main/java/com/bx/implatform/vo/GroupMessageVO.java @@ -6,6 +6,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.Date; +import java.util.List; @Data public class GroupMessageVO { @@ -19,12 +20,18 @@ public class GroupMessageVO { @ApiModelProperty(value = " 发送者id") private Long sendId; + @ApiModelProperty(value = " 发送者昵称") + private String sendNickName; + @ApiModelProperty(value = "消息内容") private String content; @ApiModelProperty(value = "消息内容类型 具体枚举值由应用层定义") private Integer type; + @ApiModelProperty(value = "@用户列表") + private List atUserIds; + @ApiModelProperty(value = " 状态") private Integer status; diff --git a/im-platform/src/main/resources/db/db.sql b/im-platform/src/main/resources/db/db.sql index 9cca837..2469150 100644 --- a/im-platform/src/main/resources/db/db.sql +++ b/im-platform/src/main/resources/db/db.sql @@ -67,7 +67,9 @@ create table `im_group_message`( `id` bigint not null auto_increment primary key comment 'id', `group_id` bigint not null comment '群id', `send_id` bigint not null comment '发送用户id', + `send_nick_name` varchar(255) DEFAULT '' comment '发送用户昵称', `content` text comment '发送内容', + `at_user_ids` varchar(1024) comment '@的用户id列表', `type` tinyint(1) NOT NULL comment '消息类型 0:文字 1:图片 2:文件 3:语音 10:系统提示' , `status` tinyint(1) DEFAULT 0 comment '状态 0:正常 2:撤回', `send_time` datetime DEFAULT CURRENT_TIMESTAMP comment '发送时间', diff --git a/im-ui/src/components/chat/ChatAtBox.vue b/im-ui/src/components/chat/ChatAtBox.vue index 858cbbf..0616a99 100644 --- a/im-ui/src/components/chat/ChatAtBox.vue +++ b/im-ui/src/components/chat/ChatAtBox.vue @@ -2,8 +2,7 @@
-
+
@@ -28,6 +27,9 @@ type: String, default: "" }, + ownerId: { + type: Number, + }, members: { type: Array } @@ -40,19 +42,27 @@ y: 0 }, activeIdx: 0, - showMembers:[] + showMembers: [] }; }, methods: { - init(){ - this.activeIdx = 0; + init() { this.$refs.scrollBox.wrap.scrollTop = 0; - this.showMembers=[]; - this.members.forEach((m)=>{ - if(m.aliasName.startsWith(this.searchText)){ + this.showMembers = []; + let userId = this.$store.state.userStore.userInfo.id; + let name = "全体成员"; + if (this.ownerId == userId && name.startsWith(this.searchText)) { + this.showMembers.push({ + userId: -1, + aliasName: name + }) + } + this.members.forEach((m) => { + if (m.userId != userId && m.aliasName.startsWith(this.searchText)) { this.showMembers.push(m); } }) + this.activeIdx = this.showMembers.length > 0 ? 0: -1; }, open(pos) { this.show = true; @@ -69,38 +79,41 @@ } }, moveDown() { - console.log(this.activeIdx) if (this.activeIdx < this.showMembers.length - 1) { this.activeIdx++; this.scrollToActive() } }, select() { - this.onSelectMember(this.showMembers[this.activeIdx]) + if (this.activeIdx >= 0) { + this.onSelectMember(this.showMembers[this.activeIdx]) + } + this.close(); }, scrollToActive() { - console.log(this.$refs.scrollBox.wrap) if (this.activeIdx * 35 - this.$refs.scrollBox.wrap.clientHeight > this.$refs.scrollBox.wrap.scrollTop) { this.$refs.scrollBox.wrap.scrollTop += 140; if (this.$refs.scrollBox.wrap.scrollTop > this.$refs.scrollBox.wrap.scrollHeight) { this.$refs.scrollBox.wrap.scrollTop = this.$refs.scrollBox.wrap.scrollHeight } } - if (this.activeIdx * 35 < this.$refs.scrollBox.wrap.scrollTop) { this.$refs.scrollBox.wrap.scrollTop -= 140; if (this.$refs.scrollBox.wrap.scrollTop < 0) { this.$refs.scrollBox.wrap.scrollTop = 0; } } - - }, onSelectMember(member) { this.$emit("select", member); this.show = false; } }, + computed: { + isOwner() { + return this.$store.state.userStore.userInfo.id == this.ownerId; + } + }, watch: { searchText: { handler(newText, oldText) { @@ -132,6 +145,7 @@ padding-right: 5px; background-color: #fafafa; white-space: nowrap; + box-sizing: border-box; &:hover { background-color: #eeeeee; @@ -151,7 +165,7 @@ padding-left: 10px; height: 100%; text-align: left; - line-height: 35px; + line-height: 40px; white-space: nowrap; overflow: hidden; font-size: 14px; diff --git a/im-ui/src/components/chat/ChatBox.vue b/im-ui/src/components/chat/ChatBox.vue index 57e6b69..01849c8 100644 --- a/im-ui/src/components/chat/ChatBox.vue +++ b/im-ui/src/components/chat/ChatBox.vue @@ -1,5 +1,5 @@