海信医疗-远程超声管理平台-信创国产化
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

398 lines
11 KiB

<template>
<div class="message-main">
<MessageList ref="messageList" @select-contact="handleSelectContact" />
<div class="message-right">
<MessageDisplay
ref="messageDisplay"
@clear-unread="handleClearUnread"
@send-files="handleSendFiles"
@group-setting="handleGroupSetting"
@refresh-list="handleRefreshList"
/>
<MessageEditor
ref="messageEditor"
:group-info="groupInfo"
@send-message="handleSendMessage"
@update-message-status="handleUpdateMessageStatus"
@font-size-change="handleFontSizeChange"
@refresh-list="handleRefreshList"
/>
</div>
<!-- 群设置弹窗 -->
<GroupSetting
v-if="groupInfo"
ref="groupSettingRef"
:chat="currentChat"
:group-info="groupInfo"
@quit-group="handleDismissGroup"
@dismiss-group="handleDismissGroup"
@refresh-list="handleRefreshList"
/>
</div>
</template>
<script>
import { mapGetters, mapActions } from "vuex";
import MessageList from "./components/MessageList.vue";
import MessageDisplay from "./components/MessageDisplay.vue";
import GroupSetting from "./components/GroupSetting.vue";
import MessageEditor from "./components/MessageEditor.vue";
import { getMultiChatInfo, editMultiChatName } from "@/api/multichat";
import { MessageType, ContactsScene, MqttTopics } from "@/utils/constants";
export default {
name: "MessageMain",
components: {
MessageList,
MessageDisplay,
GroupSetting,
MessageEditor,
},
data() {
return {
groupInfo: null,
};
},
computed: {
...mapGetters(["mqttMessages", "currentChat", "userInfo", "mqttConnected"]),
},
watch: {
mqttMessages: {
deep: true,
handler(newMessages, oldMessages) {
const oldLen = oldMessages ? oldMessages.length : 0;
const newLen = newMessages ? newMessages.length : 0;
if (newLen > oldLen) {
for (let i = oldLen; i < newLen; i++) {
this.handleMqttMessage(newMessages[i]);
}
}
},
},
},
mounted() {
this.initMqttSubscriptions();
this.handleUrlParams();
},
beforeDestroy() {
// 清理
},
methods: {
...mapActions("mqtt", ["subscribe", "unsubscribe"]),
...mapActions("message", ["setCurrentChat"]),
// 处理URL参数,实现从通讯录发消息联动
handleUrlParams() {
const { contactId, contactName, scene } = this.$route.query;
if (contactId && scene) {
const chat = {
id: contactId,
name: contactName || "未知联系人",
scene: parseInt(scene),
avatar: "",
unread_count: 0,
last_message: "",
last_message_time: new Date().toISOString(),
};
// 设置当前聊天
this.setCurrentChat(chat);
// 如果是群聊,订阅MQTT主题
if (parseInt(scene) === ContactsScene.GROUP) {
this.subscribe(MqttTopics.MULTI_CHAT + contactId);
}
// 清除URL参数
this.$router.replace({ query: {} });
}
},
async initMqttSubscriptions() {
// 订阅个人消息主题
if (this.userInfo?.id) {
await this.subscribe(MqttTopics.PRIVATE_CHAT + this.userInfo.id);
}
},
handleMqttMessage(msg) {
const type = msg.type || msg.message_type;
switch (type) {
case MessageType.READ:
this.handleReadMessage(msg);
break;
case MessageType.TEXT:
case MessageType.IMAGE:
case MessageType.VIDEO:
case MessageType.AUDIO:
case MessageType.FILE:
case MessageType.REPORT_SHARE:
case MessageType.KNOWLEDGE_SHARE:
case MessageType.CONSULTATION_MESSAGE_INVITE:
this.handleBaseMessage(msg);
break;
case MessageType.MULTI_CHAT_INVITE:
this.handleMultiChatInvite(msg);
break;
case MessageType.MULTI_CHAT_JOIN:
this.handleMultiChatJoin(msg);
break;
case MessageType.MULTI_CHAT_EDIT:
this.handleMultiChatEdit(msg);
break;
case MessageType.MULTI_CHAT_QUIT:
this.handleMultiChatQuit(msg);
break;
case MessageType.MULTI_CHAT_DISMISS:
this.handleMultiChatDismiss(msg);
break;
case MessageType.NOTIFY_CONTENT:
this.handleNotifyContent(msg);
break;
default:
console.log("未处理的MQTT消息类型:", type, msg);
}
},
handleReadMessage(msg) {
// 更新消息已读状态
if (this.$refs.messageDisplay) {
this.$refs.messageDisplay.updateMessageStatus(msg.message_id, {
read: true,
read_status: 1,
});
}
},
handleBaseMessage(msg) {
const isSelf = msg.source_id === this.userInfo?.id;
const scene =
msg.scene ||
(msg.multi_chat_id ? ContactsScene.GROUP : ContactsScene.PRIVATE);
const targetId = msg.target_id || msg.source_id;
const contactId = isSelf ? targetId : msg.source_id;
// 如果当前正在查看该会话,展示消息
if (
this.currentChat &&
this.currentChat.id ===
(scene === ContactsScene.GROUP ? msg.multi_chat_id : contactId) &&
this.currentChat.scene === scene
) {
if (this.$refs.messageDisplay) {
this.$refs.messageDisplay.addChatMessage(msg);
}
// 标记已读
if (!isSelf) {
this.handleClearUnread(this.currentChat.id, this.currentChat.scene);
}
}
// 更新联系人列表最后消息
if (this.$refs.messageList) {
this.$refs.messageList.updateContactLastMessage(
scene === ContactsScene.GROUP ? msg.multi_chat_id : contactId,
scene,
msg,
msg.timestamp || new Date().toISOString()
);
}
},
async handleMultiChatInvite(msg) {
const payload = msg.payload || {};
const multiChatId = payload.multi_chat_id || msg.multi_chat_id;
if (!multiChatId) return;
// 订阅群主题
await this.subscribe(MqttTopics.MULTI_CHAT + multiChatId);
// 获取群详情
try {
const res = await getMultiChatInfo({ multi_chat_id: multiChatId });
const group = res.data;
if (group && this.$refs.messageList) {
this.$refs.messageList.loadContacts();
}
} catch (e) {
console.error("获取群详情失败", e);
}
},
async handleMultiChatJoin(msg) {
const multiChatId = msg.multi_chat_id || msg.payload?.multi_chat_id;
if (!multiChatId) return;
try {
await getMultiChatInfo({ multi_chat_id: multiChatId });
if (this.$refs.messageList) {
this.$refs.messageList.loadContacts();
}
} catch (e) {
console.error("获取群详情失败", e);
}
},
async handleMultiChatEdit(msg) {
const multiChatId = msg.multi_chat_id || msg.payload?.multi_chat_id;
if (!multiChatId) return;
try {
await getMultiChatInfo({ multi_chat_id: multiChatId });
if (this.$refs.messageList) {
this.$refs.messageList.loadContacts();
}
// 如果当前正在该群聊,刷新标题
if (
this.currentChat &&
this.currentChat.id === multiChatId &&
this.currentChat.scene === ContactsScene.GROUP
) {
this.$refs.messageList.loadContacts();
}
} catch (e) {
console.error("获取群详情失败", e);
}
},
handleMultiChatQuit(msg) {
const payload = msg.payload || {};
const multiChatId = payload.multi_chat_id || msg.multi_chat_id;
const quitUserId = payload.user_id || msg.source_id;
if (!multiChatId) return;
if (quitUserId === this.userInfo?.id) {
// 自己退出,取消订阅并删除列表项
this.unsubscribe(MqttTopics.MULTI_CHAT + multiChatId);
if (this.$refs.messageList) {
this.$refs.messageList.removeContact(
multiChatId,
ContactsScene.GROUP
);
}
} else {
// 他人退出,更新列表
if (this.$refs.messageList) {
this.$refs.messageList.loadContacts();
}
}
},
handleMultiChatDismiss(msg) {
const multiChatId = msg.multi_chat_id || msg.payload?.multi_chat_id;
if (!multiChatId) return;
this.unsubscribe(MqttTopics.MULTI_CHAT + multiChatId);
if (this.$refs.messageList) {
this.$refs.messageList.removeContact(multiChatId, ContactsScene.GROUP);
}
},
// 群设置修改后刷新列表
handleRefreshList() {
if (this.$refs.messageList) {
this.$refs.messageList.refreshList({ keepCurrent: true });
}
},
handleNotifyContent(msg) {
// 系统通知处理
this.$notify({
title: "系统通知",
message: msg.payload?.content || msg.content || "新通知",
type: "info",
duration: 5000,
});
},
handleSelectContact(contact) {
// 如果是群聊,订阅MQTT主题
if (contact.scene == ContactsScene.GROUP) {
this.subscribe(MqttTopics.MULTI_CHAT + contact.id);
// 保存群详情
getMultiChatInfo({ multi_chat_id: contact.id }).then((res) => {
this.groupInfo = res.data || null;
});
// 将群成员传递给编辑器
} else {
this.groupInfo = null;
}
},
handleClearUnread(contactId, scene) {
if (this.$refs.messageList) {
this.$refs.messageList.clearUnread(contactId, scene);
}
},
handleSendMessage(message) {
// 更新联系人列表
if (this.$refs.messageList) {
this.$refs.messageList.updateContactLastMessage(
message.target_id,
message.scene,
message,
new Date().toISOString()
);
}
if (this.$refs.messageDisplay) {
this.$refs.messageDisplay.addChatMessage(message);
}
// 刷新列表
this.$refs.messageList.refreshList({ selectFirst: true });
},
handleUpdateMessageStatus(messageId, updates) {
if (this.$refs.messageDisplay) {
this.$refs.messageDisplay.updateMessageStatus(messageId, updates);
}
},
handleFontSizeChange(fontSize) {
if (this.$refs.messageDisplay) {
this.$refs.messageDisplay.setFontSize(fontSize);
}
},
handleSendFiles(files) {
if (this.$refs.messageEditor) {
files.forEach((file) => {
const type = file.type.startsWith("image/")
? "image"
: file.type.startsWith("video/")
? "video"
: file.type.startsWith("audio/")
? "audio"
: "file";
this.$refs.messageEditor.sendFileMessage(file, type);
});
}
},
handleGroupSetting() {
this.$refs.groupSettingRef.loadGroupInfo();
},
handleDismissGroup(chat) {
// 解散群组逻辑
if (this.$refs.messageList) {
// 刷新列表并打开第一个
this.$refs.messageList.refreshList({ selectFirst: true });
}
},
},
};
</script>
<style lang="scss" scoped>
.message-main {
display: flex;
height: 100%;
background: #fff;
.message-right {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
}
}
</style>