Browse Source

优化: 消息支持显示发送状态

master
xsx 9 months ago
parent
commit
43078dfc90
  1. 4
      db/im-platform.sql
  2. 3
      im-platform/src/main/java/com/bx/implatform/dto/GroupMessageDTO.java
  3. 4
      im-platform/src/main/java/com/bx/implatform/dto/PrivateMessageDTO.java
  4. 6
      im-platform/src/main/java/com/bx/implatform/entity/GroupMessage.java
  5. 6
      im-platform/src/main/java/com/bx/implatform/entity/PrivateMessage.java
  6. 7
      im-platform/src/main/java/com/bx/implatform/service/impl/FileServiceImpl.java
  7. 3
      im-platform/src/main/java/com/bx/implatform/vo/GroupMessageVO.java
  8. 3
      im-platform/src/main/java/com/bx/implatform/vo/PrivateMessageVO.java
  9. 2
      im-uniapp/components/chat-message-item/chat-message-item.vue
  10. 3
      im-uniapp/pages/chat/chat-box.vue
  11. 23
      im-uniapp/store/chatStore.js
  12. 1
      im-web/src/api/wssocket.js
  13. 3
      im-web/src/components/chat/ChatBox.vue
  14. 4
      im-web/src/components/chat/ChatMessageItem.vue
  15. 23
      im-web/src/store/chatStore.js

4
db/im-platform.sql

@ -31,6 +31,7 @@ create table `im_friend`(
create table `im_private_message`(
`id` bigint not null auto_increment primary key comment 'id',
`tmp_id` varchar(32) comment '临时id,由前端生成',
`send_id` bigint not null comment '发送用户id',
`recv_id` bigint not null comment '接收用户id',
`content` text comment '发送内容',
@ -44,6 +45,7 @@ create table `im_private_message`(
create table `im_group`(
`id` bigint not null auto_increment primary key comment 'id',
`tmp_id` varchar(32) comment '临时id,由前端生成',
`name` varchar(255) not null comment '群名字',
`owner_id` bigint not null comment '群主id',
`head_image` varchar(255) default '' comment '群头像',
@ -106,5 +108,5 @@ CREATE TABLE `im_file_info` (
`upload_time` datetime DEFAULT CURRENT_TIMESTAMP comment '上传时间',
`is_permanent` tinyint DEFAULT 0 comment '是否永久文件',
`md5` VARCHAR(64) NOT NULL comment '文件md5',
UNIQUE KEY `idx_md5` (md5)
KEY `idx_md5` (md5)
) ENGINE = InnoDB CHARSET = utf8mb4 comment '文件';

3
im-platform/src/main/java/com/bx/implatform/dto/GroupMessageDTO.java

@ -13,6 +13,9 @@ import java.util.List;
@Schema(description = "群聊消息DTO")
public class GroupMessageDTO {
@Schema(description = "临时id")
private String tmpId;
@NotNull(message = "群聊id不可为空")
@Schema(description = "群聊id")
private Long groupId;

4
im-platform/src/main/java/com/bx/implatform/dto/PrivateMessageDTO.java

@ -10,11 +10,13 @@ import org.hibernate.validator.constraints.Length;
@Schema(description = "私聊消息DTO")
public class PrivateMessageDTO {
@Schema(description = "临时id")
private String tmpId;
@NotNull(message = "接收用户id不可为空")
@Schema(description = "接收用户id")
private Long recvId;
@Length(max = 1024, message = "内容长度不得大于1024")
@NotEmpty(message = "发送内容不可为空")
@Schema(description = "发送内容")

6
im-platform/src/main/java/com/bx/implatform/entity/GroupMessage.java

@ -25,6 +25,12 @@ public class GroupMessage {
@TableId
private Long id;
/**
* 临时id,由前端生成
* 作用:如果用户正在发送消息时掉线了可以通过此字段获取该消息的实际发送状态
*/
private String tmpId;
/**
* 群id
*/

6
im-platform/src/main/java/com/bx/implatform/entity/PrivateMessage.java

@ -22,6 +22,12 @@ public class PrivateMessage {
*/
private Long id;
/**
* 临时id,由前端生成
* 作用:如果用户正在发送消息时掉线了可以通过此字段获取该消息的实际发送状态
*/
private String tmpId;
/**
* 发送用户id
*/

7
im-platform/src/main/java/com/bx/implatform/service/impl/FileServiceImpl.java

@ -63,7 +63,7 @@ public class FileServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> imple
}
// 如果文件已存在,直接复用
String md5 = DigestUtils.md5DigestAsHex(file.getInputStream());
FileInfo fileInfo = findByMd5(md5);
FileInfo fileInfo = findByMd5(md5, FileType.FILE.code());
if (!Objects.isNull(fileInfo)) {
// 更新上传时间
fileInfo.setUploadTime(new Date());
@ -103,7 +103,7 @@ public class FileServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> imple
UploadImageVO vo = new UploadImageVO();
// 如果文件已存在,直接复用
String md5 = DigestUtils.md5DigestAsHex(file.getInputStream());
FileInfo fileInfo = findByMd5(md5);
FileInfo fileInfo = findByMd5(md5, FileType.IMAGE.code());
if (!Objects.isNull(fileInfo)) {
// 更新上传时间和持久化标记
fileInfo.setIsPermanent(isPermanent || fileInfo.getIsPermanent());
@ -157,9 +157,10 @@ public class FileServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> imple
};
}
private FileInfo findByMd5(String md5) {
private FileInfo findByMd5(String md5, Integer fileType) {
LambdaQueryWrapper<FileInfo> wrapper = Wrappers.lambdaQuery();
wrapper.eq(FileInfo::getMd5, md5);
wrapper.eq(FileInfo::getFileType, fileType);
return getOne(wrapper);
}

3
im-platform/src/main/java/com/bx/implatform/vo/GroupMessageVO.java

@ -14,6 +14,9 @@ public class GroupMessageVO {
@Schema(description = "消息id")
private Long id;
@Schema(description = "临时id")
private String tmpId;
@Schema(description = "群聊id")
private Long groupId;

3
im-platform/src/main/java/com/bx/implatform/vo/PrivateMessageVO.java

@ -14,6 +14,9 @@ public class PrivateMessageVO {
@Schema(description = " 消息id")
private Long id;
@Schema(description = "临时id")
private String tmpId;
@Schema(description = " 发送者id")
private Long sendId;

2
im-uniapp/components/chat-message-item/chat-message-item.vue

@ -58,7 +58,7 @@
</view>
</long-press-menu>
<view v-if="sending&&isTextMessage" class="sending">
<loading size="40" icon-color="#656adf" :mask="false"></loading>
<loading :size="40" icon-color="#656adf" :mask="false"></loading>
</view>
<view v-else-if="sendFail" @click="onSendFail"
class="send-fail iconfont icon-warning-circle-fill"></view>

3
im-uniapp/pages/chat/chat-box.vue

@ -167,6 +167,7 @@ export default {
return;
}
let msgInfo = {
tmpId: this.generateId(),
content: JSON.stringify(data),
type: this.$enums.MESSAGE_TYPE.AUDIO,
receipt: this.isReceipt
@ -307,6 +308,7 @@ export default {
let receiptText = this.isReceipt ? "【回执消息】" : "";
let atText = this.createAtText();
let msgInfo = {
tmpId: this.generateId(),
content: receiptText + sendText + atText,
atUserIds: this.atUserIds,
receipt: this.isReceipt,
@ -893,7 +895,6 @@ export default {
},
buildTmpMessage(msgInfo) {
let message = JSON.parse(JSON.stringify(msgInfo));
message.tmpId = this.generateId();
message.sendId = this.mine.id;
message.sendTime = new Date().getTime();
message.status = this.$enums.MESSAGE_STATUS.SENDING;

23
im-uniapp/store/chatStore.js

@ -30,14 +30,6 @@ export default defineStore('chatStore', {
}
this.privateMsgMaxId = chatsData.privateMsgMaxId || 0;
this.groupMsgMaxId = chatsData.groupMsgMaxId || 0;
// 防止消息一直处在发送中状态
cacheChats.forEach(chat => {
chat.messages.forEach(msg => {
if (msg.status == MESSAGE_STATUS.SENDING) {
msg.status = MESSAGE_STATUS.FAILED
}
})
})
},
openChat(chatInfo) {
let chats = this.curChats;
@ -63,6 +55,7 @@ export default defineStore('chatStore', {
lastSendTime: new Date().getTime(),
unreadCount: 0,
hotMinIdx: 0,
readedMessageIdx: 0,
messages: [],
atMe: false,
atAll: false,
@ -95,15 +88,17 @@ export default defineStore('chatStore', {
readedMessage(pos) {
let chat = this.findChatByFriend(pos.friendId);
if (!chat) return;
chat.messages.forEach((m) => {
for (let idx = chat.readedMessageIdx; idx < chat.messages.length; idx++) {
let m = chat.messages[idx];
if (m.id && m.selfSend && m.status < MESSAGE_STATUS.RECALL) {
// pos.maxId为空表示整个会话已读
if (!pos.maxId || m.id <= pos.maxId) {
m.status = MESSAGE_STATUS.READED
chat.readedMessageIdx = idx;
chat.stored = false;
}
}
})
}
if (!chat.stored) {
this.saveToStorage();
}
@ -463,11 +458,19 @@ export default defineStore('chatStore', {
if (!coldChat && !hotChat) {
return;
}
// 防止消息一直处在发送中状态
hotChat && hotChat.messages.forEach(msg => {
if (msg.status == MESSAGE_STATUS.SENDING) {
msg.status = MESSAGE_STATUS.FAILED
}
})
// 冷热消息合并
let chat = Object.assign({}, coldChat, hotChat);
if (hotChat && coldChat) {
chat.messages = coldChat.messages.concat(hotChat.messages)
}
// 历史版本没有readedMessageIdx字段,做兼容一下
chat.readedMessageIdx = chat.readedMessageIdx || 0;
chatsData.chats.push(chat);
})
}

1
im-web/src/api/wssocket.js

@ -92,7 +92,6 @@ let heartCheck = {
websock.send(JSON.stringify(heartBeat))
}
},
reset: function () {
clearTimeout(this.timeoutObj);
this.timeoutObj = setTimeout(function () {

3
im-web/src/components/chat/ChatBox.vue

@ -361,6 +361,7 @@ export default {
return;
}
let msgInfo = {
tmpId: this.generateId(),
content: JSON.stringify(data),
type: this.$enums.MESSAGE_TYPE.AUDIO,
receipt: this.isReceipt
@ -452,6 +453,7 @@ export default {
reject();
}
let msgInfo = {
tmpId: this.generateId(),
content: sendText,
type: this.$enums.MESSAGE_TYPE.TEXT
}
@ -670,7 +672,6 @@ export default {
},
buildTmpMessage(msgInfo) {
let message = JSON.parse(JSON.stringify(msgInfo));
message.tmpId = this.generateId();
message.sendId = this.mine.id;
message.sendTime = new Date().getTime();
message.status = this.$enums.MESSAGE_STATUS.SENDING;

4
im-web/src/components/chat/ChatMessageItem.vue

@ -254,7 +254,7 @@ export default {
.message-content-wrapper {
position: relative;
display: flex;
align-items: end;
align-items: center;
.sending {
width: 25px;
@ -270,7 +270,7 @@ export default {
color: #e45050;
font-size: 30px;
cursor: pointer;
margin: 0 20px;
margin: 0 3px;
}
}

23
im-web/src/store/chatStore.js

@ -40,14 +40,6 @@ export default defineStore('chatStore', {
this.privateMsgMaxId = chatsData.privateMsgMaxId || 0;
this.groupMsgMaxId = chatsData.groupMsgMaxId || 0;
cacheChats = chatsData.chats || [];
// 防止消息一直处在发送中状态
cacheChats.forEach(chat => {
chat.messages.forEach(msg => {
if (msg.status == MESSAGE_STATUS.SENDING) {
msg.status = MESSAGE_STATUS.FAILED
}
})
})
},
openChat(chatInfo) {
let chats = this.findChats()
@ -73,6 +65,7 @@ export default defineStore('chatStore', {
lastSendTime: new Date().getTime(),
unreadCount: 0,
hotMinIdx: 0,
readedMessageIdx: 0,
messages: [],
atMe: false,
atAll: false,
@ -103,15 +96,17 @@ export default defineStore('chatStore', {
readedMessage(pos) {
let chat = this.findChatByFriend(pos.friendId);
if (!chat) return;
chat.messages.forEach((m) => {
for (let idx = chat.readedMessageIdx; idx < chat.messages.length; idx++) {
let m = chat.messages[idx];
if (m.id && m.selfSend && m.status < MESSAGE_STATUS.RECALL) {
// pos.maxId为空表示整个会话已读
if (!pos.maxId || m.id <= pos.maxId) {
m.status = MESSAGE_STATUS.READED
chat.readedMessageIdx = idx;
chat.stored = false;
}
}
})
}
this.saveToStorage();
},
removeChat(idx) {
@ -474,11 +469,19 @@ export default defineStore('chatStore', {
}
let coldChat = chats[i];
let hotChat = chats[i + 1];
// 防止消息一直处在发送中状态
hotChat && hotChat.messages.forEach(msg => {
if (msg.status == MESSAGE_STATUS.SENDING) {
msg.status = MESSAGE_STATUS.FAILED
}
})
// 冷热消息合并
let chat = Object.assign({}, coldChat, hotChat);
if (hotChat && coldChat) {
chat.messages = coldChat.messages.concat(hotChat.messages)
}
// 历史版本没有readedMessageIdx字段,做兼容一下
chat.readedMessageIdx = chat.readedMessageIdx || 0;
chatsData.chats.push(chat);
}
this.initChats(chatsData);

Loading…
Cancel
Save